🍺小沐学python系列文章汇总:🍺
🎈【小沐学python】(一)Python简介和安装🎈🎈【小沐学python】(二)Python常见问题汇总🎈
本节目录:
某天,戈戈来到江边静坐凝思,一手放着风筝,一手钓着鱼。水面粼粼,微风徐徐,柳枝招摇。
1、论语篇
戈戈:《论语》读了许多天可有心得?
狄狄:错误要么是“过了”,要么是“不及”,重要的就是把握住度。
1.1 历史
Python(英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/), 是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,第一个公开发行版发行于1991年。
1.2 安装
python官网下载地址:
https://www.python.org/downloads/ python安装完后,在开始菜单会有如下的子菜单:
python安装后的子菜单介绍如下:
- IDLE:由python之父开发的一个小型的python开发环境,可以用来解释执行python代码,也可以用来写python脚本。
- Python:这个就是python的解释器,可以用来解释执行python代码,使用命令行调用python命令的时候就是运行的这个程序。
- Python Manuals:这个是python的使用手册,可以用来学习python的基础使用。
- Python Module Docs:这个是python的模块文档,可以用来学习模块的使用。
python代码的执行方式有两种:
2、理学篇(基本类型)
戈戈:程朱理学常说格物致知。那些红绿线平时可格出了些什么?
狄狄:随机漫步的傻瓜,价值,习惯没时间看。
2.1 关键字(保留字)
>>> import keyword
>>> keyword.kwlist
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
2.2 内置函数
https://docs.python.org/zh-cn/3.10/library/functions.html Python 解释器内置了很多函数和类型,任何时候都能使用。以下按字母顺序给出列表。
2.3 变量的定义
Python 是弱类型的语言:
- 在强类型的编程语言中,定义变量时要指明变量的类型,而且赋值的数据也必须是相同类型的,C语言、C++、Java 是强类型语言的代表。
- 和强类型语言相对应的是弱类型语言,Python、JavaScript、PHP 等脚本语言一般都是弱类型的。
弱类型语言有两个特点:
- 变量无须声明就可以直接赋值,对一个不存在的变量赋值就相当于定义了一个新变量。
- 变量的数据类型可以随时改变,比如,同一个变量可以一会儿被赋值为整数,一会儿被赋值为字符串。
(1)整数类型
整数就是没有小数部分的数字,Python 中的整数包括正整数、0 和负整数。
(2)浮点数类型
Python 只有一种小数类型,就是 float。C语言有两种小数类型,分别是 float 和 double。
Python 中的小数有两种书写形式:
- 十进制形式
这种就是我们平时看到的小数形式,例如 34.6、346.0、0.346。 - 指数形式
Python 小数的指数形式的写法为:
aEn 或 aen
举例如下:
2.1E5 = 2.1×105,其中 2.1 是尾数,5 是指数。
3.7E-2 = 3.7×10-2,其中 3.7 是尾数,-2 是指数。
0.5E7 = 0.5×107,其中 0.5
(3)复数类型
复数(Complex)是 Python 的内置类型,直接书写即可。
(4)字符串类型
若干个字符的集合就是一个字符串(String)。Python 中的字符串必须由双引号" "或者单引号’ '包围。
(5)布尔类型
Python 提供了 bool 类型来表示真(对)或假(错),True 和 False 是 Python 中的关键字,当作为 Python 代码输入时,一定要注意字母的大小写,否则解释器会报错。
2.4 运算符
- 算术运算符
- 比较(关系)运算符
- 赋值运算符
- 逻辑运算符
- 位运算符
- 成员运算符
- 身份运算符
2.5 输入输出
- print() 函数
用于输出一个或多个值。
print (value,…,sep=‘’,end=‘\n’,file=sys.stdout,flush=False)
print("读者名:" ,user_name,"年龄:",user_age,sep='|')
- input() 函数
用于从控制台读取用户输入的内容。
str = input("Please input:")
3、心学篇(数组类型)
戈戈:你未看此花时,此花与汝心同归于寂。你来看此花时,则此花颜色一时明白起来。便知此花不在你的心外。
狄狄:修道了嚒,神神叨叨的…
3.1 列表
列表(list)也是最常用的 Python 数据类型之一,它以一个方括号内包含多个其他数据项,数据项间以逗号作为分隔的数据类型。
list1 = ['Hello', 'World', 1900, 2021]
print(list1)
3.2 元组
Python 的元组(tuple,简写为tup)与列表类似,不同之处在于元组的元素不能修改。
元组使用小括号(),列表使用方括号[]。
tup1 = ('Hello', 'Apple', 1900, 2021)
print(tup1)
3.3 字典
在Python3中字典(dictionary ,简写为dict)是另一种可变容器模型,且可存储任意类型对象。
字典的每个键值 (key=>value) 对用冒号 (😃 分割,每个对之间用逗号 (,) 分割,整个字典包括在花括号 ({}) 中。
键必须是唯一的,但值则不必。
dict = {'Apple': '5999', 'Huawei': '8989', 'Xiaomi': '699'}
print(dict)
3.4 集合
集合(set)是一个无序的不重复元素序列。,但元素的排列顺序却不是固定的。
basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
print(basket)
4、稻盛篇(文件操作)
戈戈:稻盛心学教人一心一意磨炼心灵,到达真我,瞬间明白一切真理。可对?
狄狄:适度鸡汤也可以的,不要刻意。
4.1 文件操作
检验给出的路径是否是一个文件:os.path.isfile()
检验给出的路径是否是一个目录:os.path.isdir()
判断是否是绝对路径:os.path.isabs()
返回一个路径的目录名和文件名:os.path.split()
举例:os.path.split(‘/home/swaroop/byte/code/poem.txt’)
结果:(‘/home/swaroop/byte/code’, ‘poem.txt’)
分离扩展名:os.path.splitext()
获取路径名:os.path.dirname()
获取文件名:os.path.basename()
读取和设置环境变量:os.getenv() 与os.putenv()
给出当前平台使用的行终止符:os.linesep Windows使用’\r\n’,Linux使用’\n’而Mac使用’\r’
指示你正在使用的平台:os.name 对于Windows,它是’nt’,而对于Linux/Unix用户,它是’posix’
终止当前进程:os.exit()
运行shell命令: os.system()
获取文件属性:os.stat(file)
获取文件大小:os.path.getsize(filename)
修改文件权限与时间戳:os.chmod(file)
重命名:os.rename(old, new)
返回指定目录下的所有文件和目录名: os.listdir()
得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd()
检验给出的路径是否真地存: os.path.exists()
创建多级目录:os.makedirs(r"c:\python\test")
创建单个目录:os.mkdir("test")
删除多级目录:os.removedirs(r"c:\python")
删除单个文件:os.remove(path)
os.mknod("test.txt") #创建空文件
fp = open("test.txt", 'w') #直接打开一个文件,如果文件不存在则创建文件
'''
关于open 模式:
w 以写方式打开,
a 以追加模式打开 (从 EOF 开始, 必要时创建新文件)
r+ 以读写模式打开
w+ 以读写模式打开 (参见 w )
a+ 以读写模式打开 (参见 a )
rb 以二进制读模式打开
wb 以二进制写模式打开 (参见 w )
ab 以二进制追加模式打开 (参见 a )
rb+ 以二进制读写模式打开 (参见 r+ )
wb+ 以二进制读写模式打开 (参见 w+ )
ab+ 以二进制读写模式打开 (参见 a+ )
'''
4.2 目录操作
创建目录:
os.mkdir(“file”)
转换目录:
os.chdir(“path”)
复制文件:
shutil.copyfile(“oldfile”,“newfile”) oldfile和newfile都只能是文件
shutil.copy(“oldfile”,“newfile”) oldfile只能是文件夹,newfile可以是文件,也可以是目标目录
复制文件夹:
shutil.copytree(“olddir”,“newdir”) olddir和newdir都只能是目录,且newdir必须不存在
重命名文件(目录):
os.rename(“oldname”,“newname”) 文件或目录都是使用这条命令
移动文件(目录)
shutil.move(“oldpos”,“newpos”)
删除文件:
os.remove("file")
删除目录:
os.rmdir("dir")只能删除空目录
shutil.rmtree("dir")
4.3 json
在python中JSON对应的数据类型是字典,可以使用json库来进行JSON和python字典的互转.
json.dumps() #将python对象编码成Json字符串
json.loads() #将Json字符串解码成python对象
json.dump() #将python中的对象转化成json储存到文件中
json.load() #将文件中的json的格式转化成python对象提取
import json
#将python对象转换为json字符串
persons = [
{
'username': "zhaoji",
"age": "18",
"country": "China"
},
{
"username": "cyj",
"age": "18",
"country": "China"
}
]
## json.dumps
json_str = json.dumps(persons)
## json.dump
with open("./data/j1.json", "w") as fp:
json.dump(persons, fp)
4.4 xml
<?xml version="1.0" encoding="utf-8"?>
<catalog>
<maxid>11111</maxid>
<login username="test" passwd='123456'>
<caption>Python</caption>
<item id="4">
<caption>测试</caption>
</item>
</login>
<item id="2">
<caption>cat</caption>
</item>
</catalog>
#coding=utf-8
import xml.dom.minidom
#打开xml文档
dom = xml.dom.minidom.parse('abc.xml')
#得到文档元素对象
root = dom.documentElement
bb = root.getElementsByTagName('maxid')
b= bb[0]
print(b.nodeName)
bb = root.getElementsByTagName('login')
b= bb[0]
print(b.nodeName)
4.5 re
RegEx 或正则表达式是形成搜索模式的字符序列。
RegEx 可用于检查字符串是否包含指定的搜索模式。
Python 提供名为 re 的内置包,可用于处理正则表达式。
函数
| 描述
|
findall
| 返回包含所有匹配项的列表
|
search
| 如果字符串中的任意位置存在匹配,则返回 Match 对象
|
split
| 返回在每次匹配时拆分字符串的列表
|
sub
| 用字符串替换一个或多个匹配项
|
import re
fn = open("d:/xx.txt", "r",encoding='utf-8')
str = fn.read()
http_arrs = re.findall(r"(http.*)\";", str)
print(len(http_arrs))
http_arrs = list(set(list(http_arrs)))
http_arrs.sort()
print(len(http_arrs))
for h in http_arrs:
print('"' + h + '",')
# a = ''.join(a)
# print(a)
4.6 pandas
#-- coding: utf-8 --
import pandas as pd
## 读取excel数据
# data = [['202104',10000,None],['202105',10000,None],['202106',200001,None],['202107',200000,None]]
# df = pd.DataFrame(data,columns=['time','revenue', 'rate'])
file_path = r'd:/test.xlsx'
df = pd.read_excel(file_path, sheet_name = "Sheet1")
## 方法1
df.loc[df['revenue'] <100000, ['rate']] = 0.06
df.loc[(df['revenue'] >=100000) & (df['revenue'] <200000), ['rate']]= 0.1
df.loc[df['revenue'] >=200000, ['rate']] = 0.14
print(df)
## 方法2
def calcRate(df):
if df['revenue'] <100000:
return '6%'
elif df['revenue'] >=100000 and df['revenue'] <200000:
return '10%'
else:
return '14%'
# df['rate']=df.apply(calcRate,axis=1)
# print(df)
## 另存excel数据
df.to_excel(r'd:/out.xlsx', sheet_name='Sheet1', index=False, header=True)
#-- coding: utf-8 --
import pandas as pd
df = pd.DataFrame()
for i in range(1, 5):
url = f'http://vip.stock.finance.sina.com.cn/q/go.php/vComStockHold/kind/jjzc/index.phtml?p={i}%27'
df = pd.concat([df, pd.read_html(url)[0].iloc[::,:-1]])
# df['代码'].apply(str)
# df['代码'] = df['代码'].astype(str)
# df['代码'] = df['代码'].apply(lambda _: str(_))
df['代码'] = df['代码'].astype(int)
df['代码'] = df['代码'].map(lambda x:('%06d')%x).apply(str)
df['代码'] = '="' + df['代码'] + '"'
df.to_csv('test.csv', encoding='utf_8_sig', index=False)
df.to_excel(r'test.xlsx', sheet_name='Sheet1', index=False, header=True)
注意:Excel打开CSV文件,数字起始0丢失问题。
0123456->="0123456"
1.0123456->"1.0123456"
xiaomi,hello->"xiaomi,hello"
ni"wo,ta->"ni""wo,ta"
# -*- coding: utf-8 -*-
import pandas as pd
## 读取excel文件
df = pd.read_excel(r'd:\excel_in.xlsx')
## 进行数据透视处理
df2 = df.pivot(index=['ID' , '姓名' , '年龄'], columns='检测项目',values='检测结果')
df3 = df2.reset_index()
## 将空值替换成自定义的文本
df3.fillna(value='空缺', inplace=True)
print(df3)
## 结果保存excel文件
df3.to_excel(r'd:\excel_output.xlsx', na_rep=True)
4.7 opencv
import cv2
import numpy as np
import base64
# numpy 转 base64
def numpy_to_base64(image_np):
data = cv2.imencode('.jpg', image_np)[1]
image_bytes = data.tobytes()
image_base4 = base64.b64encode(image_bytes).decode('utf8')
return image_base4
# numpy 转 bytes
def numpy_to_bytes(image_np):
data = cv2.imencode('.jpg', image_np)[1]
image_bytes = data.tobytes()
return image_bytes
# 数组保存
def numpy_to_file(image_np):
filename = '你的文件名_numpy.jpg'
cv2.imwrite(filename,image_np)
return filename
# bytes转数组
def bytes_to_numpy(image_bytes):
image_np = np.frombuffer(image_bytes, dtype=np.uint8)
image_np2 = cv2.imdecode(image_np, cv2.IMREAD_COLOR)
return image_np2
# bytes 转 base64
def bytes_to_base64(image_bytes):
image_base4 = base64.b64encode(image_bytes).decode('utf8')
return image_base4
# bytes 保存
def bytes_to_file(image_bytes):
filename = '你的文件名_bytes.jpg'
with open(filename,'wb') as f:
f.write(image_bytes)
return filename
# 文件 转 数组
def file_to_numpy(path_file):
image_np = cv2.imread(path_file)
return image_np
# 文件转 字节
def file_to_bytes(path_file):
with open(path_file,'rb') as f:
image_bytes = f.read()
return image_bytes
# 文件转base64
def file_to_base64(path_file):
with open(path_file,'rb') as f:
image_bytes = f.read()
image_base64 = base64.b64encode(image_bytes).decode('utf8')
return image_base64
# base64 转 bytes
def base64_to_bytes(image_base64):
image_bytes = base64.b64decode(image_base64)
return image_bytes
# base64转数组
def base64_to_numpy(image_base64):
image_bytes = base64.b64decode(image_base64)
image_np = np.frombuffer(image_bytes, dtype=np.uint8)
image_np2 = cv2.imdecode(image_np, cv2.IMREAD_COLOR)
return image_np2
# base64 保存
def base64_to_file(image_base64):
filename = '你的文件名_base64.jpg'
image_bytes = base64.b64decode(image_base64)
with open(filename, 'wb') as f:
f.write(image_bytes)
return filename
def main():
pass
if __name__ == "__main__":
main()
5、天道篇(点云绘制)
狄狄:累死了。
戈戈:丁元英告诉年轻人不要轻易说这个词,说完就真的马上要倒下。想干成点事,别把别人看得太轻,别把自己看得太重。
戈戈:我想找个井沿扒着看看,哪有?
狄狄:农村。这盘菜不是人人都能吃得,扒上了饱了眼福,再掉下去可就跌入了地狱。
点云是在同一空间参考系下表达目标空间分布和目标表面特性的海量点集合,物体表面设置多个采样点获取这些点的信息,这些点包含了丰富的信息,包括三维坐标X,Y,Z、颜色、分类值、强度值、时间等等,而大量这种点组成的点集合就称之为点云(Point Cloud)。
5.1 vtk库显示点云
使用vtk开源库C++实现
https://vtk.org/about/#overview
5.2 pyvista库显示点云
使用python库pyvista绘制点云。
https://docs.pyvista.org/examples/00-load/create-point-cloud.html
5.3 PCL库显示点云
Point Cloud Library (PCL)是一个功能强大的开源C++库。
https://github.com/PointCloudLibrary/pcl/releaseshttps://pointclouds.org/
5.4 Qt库显示点云
使用QT的QVTKWideget模块绘制点云(Qt+VTK+PCL方案)
https://vtk.org/doc/release/7.1/html/classQVTKWidget.html
5.5 matlab库显示点云
基于matlab的点云重建与三角剖分
https://ww2.mathworks.cn/help/vision/ref/pcread.htmlhttps://ww2.mathworks.cn/help/vision/point-cloud-processing.html?s_tid=CRUX_lftnav
ptCloud = pcread(filename) 从PLY、PCD读取指定路径的点云。反回一个pointCloud对象。
pcshow(ptCloud)
pcshow(xyzPoints)
pcshow(xyzPoints,C)
pcshow(filename)
pcshow(___,Name,Value)
ax = pcshow(___)
5.6 Open3D库显示点云
Open3D和PCL都是很优秀的三维数据处理库。Open3D是一个开源库,支持快速开发处理3D数据的软件。Open3D前端在C++和Python中公开了一组精心挑选的数据结构和算法。后端经过高度优化,并设置为并行化。Open3D作为新库,算法不如PCL多,个人感觉它对Python支持较好,可视化效果较好。
http://www.open3d.org/docs/release/
5.7 tecplot库显示点云
Tecplot是一款功能强大的数据分析和可视化处理软件。它提供了丰富的绘图格式,包括x-y曲线图,多种格式的的2-D和3-D面绘图。而且针对于Fluent软件有专门的数据接口,可以直接读入*.cas和*.dat文件,也可以在Fluent软件中选择输出的面和变量,然后直接输出tecplot格式文档。
https://people.math.sc.edu/Burkardt/f_src/tec_io/tec_io.htmlhttps://people.sc.fsu.edu/~jburkardt/data/tec/tec.html
6、佛家篇(绘图)
狄狄:您再写一篇经文大概需要几个小时啊?
戈戈:佛曰: 不可说,不可说,一说就得背锅。
6.1 绘制自定义图形(turtle )
import turtle
turtle.color('green', 'green')
turtle.pensize(2)
turtle.circle(10)
turtle.circle(40)
turtle.forward(100)
turtle.circle(10)
turtle.circle(40)
turtle.exitonclick() #上面的绘制完毕之后,点击画面时画布窗口才会关闭,然后才执行后面的代码
# turtle.mainloop() #这种方法会使得后面的代码无法运行
#turtle.done() #这种方法会使得后面的代码无法运行
7、立志篇(控件)
戈戈:放假前交代的功课做了没?
狄狄:说不清,道不明,杂事一堆。
戈戈:人不立志,天下无有可成之事。
狄狄:师父今天很闲啊。
7.1 分页控件(tkinter, Notebook)
import tkinter
import tkinter.ttk
root = tkinter.Tk()
root.geometry('300x180')
notebook = tkinter.ttk.Notebook(root)
#Panedwindow
frameOne = tkinter.Frame()
frameTwo = tkinter.Frame()
frameThree = tkinter.Frame()
notebook.add(frameOne, text='选项卡1')
notebook.add(frameTwo, text='选项卡2')
notebook.add(frameThree, text='选项卡3')
notebook.pack(padx=10, pady=5, fill=tkinter.BOTH, expand=True)
root.mainloop()
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
style = ttk.Style(root)
style.configure('lefttab.TNotebook', tabposition='wn')
# style.configure('lefttab.TNotebook', tabposition='ws')
notebook = ttk.Notebook(root, style='lefttab.TNotebook')
f1 = tk.Frame(notebook, bg='gray', width=200, height=200)
f2 = tk.Frame(notebook, bg='blue', width=200, height=200)
f3 = tk.Frame(notebook, bg='green', width=200, height=200)
notebook.add(f1, text='Frame 1')
notebook.add(f2, text='Frame 2')
notebook.add(f3, text='Frame 3')
notebook.pack()
root.mainloop()
7.2 进度条控件(tkinter, Canvas)
import time,os,sys
import tkinter.messagebox
from tkinter import *
def createTKWindow():
root = tkinter.Tk()
root.withdraw()
return root
def closeTkWindow(root):
root.destroy()
def showAskWindow():
wen = tkinter.messagebox.askokcancel('!','确定开始去炼丹吗?')
if not wen:
os._exit()
else:
root.wm_deiconify()
# 更新进度条函数
def change_schedule(win, now_schedule, all_schedule):
percent = (now_schedule/all_schedule)*100
canvas.coords(fill_rec, (5, 5, percent*processbar_w*0.01, 25))
x.set(str(round(percent, 2)) + '%')
win.update()
# 窗口关闭事件
def on_closing():
running = False
root.destroy()
# 创建画布
running = True
processbar_w = 250
root = createTKWindow()
sw = root.winfo_screenwidth()
sh = root.winfo_screenheight()
ww = processbar_w + 50
wh = 30
x = (sw-ww) / 2
y = (sh-wh) / 2
root.geometry("%dx%d+%d+%d" %(ww,wh,x,y))
root.resizable(0,0) # 禁止拉伸窗口
#root.overrideredirect(1) # 隐藏标题栏 最大化最小化按钮
#root.attributes("-toolwindow", 2) # 去掉窗口最大化最小化按钮,只保留关闭
root.title('Coming')
root.protocol("WM_DELETE_WINDOW", on_closing)
frame = Frame(root).grid(row=0, column=0)
canvas = Canvas(frame, width=processbar_w, height=30, bg="white")
canvas.grid(row=0, column=0)
x = StringVar()
# 进度条以及完成程度
out_rec = canvas.create_rectangle(5, 5, processbar_w, 25, outline="", width=1)
fill_rec = canvas.create_rectangle(5, 5, 5, 25, outline="", width=0, fill="red")
Label(frame, textvariable=x).grid(row=0, column=1)
showAskWindow()
for i in range(100+1):
time.sleep(0.01)
change_schedule(root, i, 100)
closeTkWindow(root)
7.3 弹框控件(tkinter, messagebox, filedialog )
import tkinter
import tkinter.messagebox #弹窗库
#1、提示消息框
tkinter.messagebox.showinfo('提示','今天星期一')
#2、消息警告框
tkinter.messagebox.showwarning('警告','明日有大雨')
#3、错误消息框
tkinter.messagebox.showerror('错误','系统崩溃了!')
#4、对话框
tkinter.messagebox.askokcancel('提示', '要执行此操作吗')#确定/取消,返回值true/false
tkinter.messagebox.askquestion('提示', '要执行此操作吗')#是/否,返回值yes/no
tkinter.messagebox.askyesno('提示', '要执行此操作吗')#是/否,返回值true/false
tkinter.messagebox.askretrycancel('提示', '要执行此操作吗')#重试/取消,返回值true/false
#5、文件对话框
import tkinter.filedialog
a=tkinter.filedialog.asksaveasfilename()#返回文件名
print(a)
a =tkinter.filedialog.asksaveasfile()#会创建文件
print(a)
a =tkinter.filedialog.askopenfilename()#返回文件名
print(a)
a =tkinter.filedialog.askopenfile()#返回文件流对象
print(a)
a =tkinter.filedialog.askdirectory()#返回目录名
print(a)
a =tkinter.filedialog.askopenfilenames()#可以返回多个文件名
print(a)
a =tkinter.filedialog.askopenfiles()#多个文件流对象
print(a)
8、道家篇(界面库)
戈戈:最近大家都在说躺平。
狄狄:我也想。
8.1 PySide2
https://pypi.org/project/PySide2/
PySide2 是来自 Qt for Python 项目的官方 Python 模块,它提供对完整 Qt 5.12+ 框架的访问。
Qt for Python 项目是开放式开发的,具有您期望从任何现代 OSS 项目中获得的所有功能,例如 git 存储库中的所有代码和开放式设计过程。我们欢迎任何符合 Qt 贡献协议的贡献。
import sys
from PySide2.QtWidgets import QApplication, QPushButton
app = QApplication(sys.argv)
window = QPushButton("Push Me")
window.show()
app.exec_()
#!python3
# encoding:utf-8
from PySide2 import QtWidgets
from PySide2 import QtCore
class Window(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setWindowTitle("Sample")
self.setStyleSheet("background-color:white;")
self.setFixedSize(480, 320)
hbox = QtWidgets.QHBoxLayout()
vbox = QtWidgets.QVBoxLayout()
hbox.addLayout(vbox)
button_first = QtWidgets.QPushButton("Button: 1")
button_first.setStyleSheet("background-color:gray; color:white;height:100%")
vbox.addWidget(button_first)
button_second = QtWidgets.QPushButton("Button: 2")
button_second.setStyleSheet("background-color:darkgray; color:white;height:100%")
vbox.addWidget(button_second)
textedit = QtWidgets.QTextEdit("QtWidgets.QTextEdit")
textedit.setStyleSheet("background-color:lightgray;")
hbox.addWidget(textedit)
self.setLayout(hbox)
if __name__ == "__main__":
app = QtWidgets.QApplication()
window = Window()
window.show()
exit(app.exec_())
8.2 PyQt5
https://pypi.org/project/PyQt5/
Qt 是一组跨平台的 C++ 库,它们实现了用于访问现代桌面和移动系统的许多方面的高级 API。其中包括定位和定位服务、多媒体、NFC 和蓝牙连接、基于 Chromium 的 Web 浏览器以及传统的 UI 开发。
PyQt5 是一套针对 Qt v5 的综合 Python 绑定。它被实现为超过 35 个扩展模块,使 Python 能够在所有支持的平台(包括 iOS 和 Android)上用作 C++ 的替代应用程序开发语言。
PyQt5 也可以嵌入基于 C++ 的应用程序中,以允许这些应用程序的用户配置或增强这些应用程序的功能。
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("软件名称")
window.resize(600,500)
btn = QPushButton(window)
btn.setText("按钮")
btn.resize(120, 30)
btn.move(100, 100)
btn.setStyleSheet('background-color:green;font-size:16px;')
label =QLabel(window)
label.setText('标签')
label.setStyleSheet('background-color:green;font-size:16px;')
# label.show()
window.show()
sys.exit(app.exec_())
9、西游篇(辅助)
戈戈:有人说孙悟空头上的有形紧箍内化为他心里的无形紧箍了。
狄狄:师父,我先回去了。
幕落。
9.1 RPA(机器人自动化)
RPA是Robotic Process Automation。中文是机器人流程自动化,利用软件将重复性的工作自动化。基本目标是让人从重复性强的繁琐工作中解放出来去做更有意义更具创造性的工作。
RPA的概念是由一家研发此类软件的IT创业公司和一家研究机构在2012年所提出的。当前还未有明确的定义概念,RPA的概念主要通过厂商和用户不断地实践总结、口耳相传而逐步推广开来。
9.2 rsa加密解密
- (1)rsa库
Python中使用RSA库生成公钥和私钥,只能以PKCS#1 DER或PEM格式保存公钥和私钥。但是有时会遇到PKCS#8这种格式。
import os
import rsa
# 生成一对公钥和私钥
public_key, private_key = rsa.newkeys(2048)
# 将公钥以PKCS#1格式写入文件
with open('pub_pkcs1.pem', 'wb') as fp:
fp.write(public_key.save_pkcs1())
# 将私钥以PKCS#1格式写入文件
with open('pri_pkcs1.pem', 'wb') as fp:
fp.write(private_key.save_pkcs1())
# 将公钥由PKCS#1格式转为PKCS#8格式
os.system('openssl rsa --RSAPublicKey_in -in {}.pem -out {}.pem'.format('pub_pkcs1', 'pub_pkcs8'))
# 将私钥由PKCS#1格式转为PKCS#8格式
os.system('openssl pkcs8 -topk8 -inform PEM -in {}.pem -outform pem -nocrypt -out {}.pem'.format('pri_pkcs1', 'pri_pkcs8'))
- 生成一个私钥:(通过命令openssl.exe实现)
# 生成一个私钥,推荐使用1024位的秘钥,秘钥以pem格式保存到-out参数指定的文件中,采用PKCS1格式
openssl genrsa -out pri_pkcs1.pem 1024
- pkcs1格式私钥转为pkcs8格式私钥:(通过命令openssl.exe实现)
openssl pkcs8 -topk8 -inform PEM -in pri_pkcs1.pem -outform pem -nocrypt -out pri_pkcs8.pem
- pkcs8格式私钥转为pkcs1格式私钥:(通过命令openssl.exe实现)
openssl rsa -in d:\pri_pkcs8.pem -out d:\pri_pkcs1.pem
or
openssl pkcs8 -in pri_pkcs8.pem -nocrypt -out pri_pkcs1.pem
- pkcs8格式私钥生成pkcs8格式公钥:(通过命令openssl.exe实现)
openssl rsa -in pri_pkcs8.pem -pubout -out pub_pkcs8.pem
import rsa
import base64
from urllib import request
def create_new_keys(lens):
(public_key, private_key) = rsa.newkeys(lens)
with open('pub_pkcs1.pem', 'wb') as f:
f.write(public_key.save_pkcs1())
with open('pri_pkcs1.pem', 'wb') as f:
f.write(private_key.save_pkcs1())
def rsa_encrypt(msg):
with open(PUBLIC_FILE_PATH, 'rb') as public_file:
public_key = rsa.PublicKey.load_pkcs1_openssl_pem(public_file.read())
code = rsa.encrypt(msg.encode('utf-8'), public_key)
code = base64.b64encode(code).decode('utf-8')
code = request.quote(code)
return code
def rsa_decrypt(code):
code = request.unquote(code)
with open(PRIVATE_FILE_PATH, 'rb') as private_file:
private_key = rsa.PrivateKey.load_pkcs1(private_file.read())
code = base64.b64decode(code.encode('utf-8'))
msg = rsa.decrypt(code, private_key).decode('utf-8')
return
import rsa
# 先生成一对密钥,然后保存.pem格式文件,当然也可以直接使用
(pubkey, privkey) = rsa.newkeys(1024)
print(rsa.common.bit_size(privkey.n)) #1024
print(rsa.common.byte_size(privkey.n)) #128
# 用公钥加密、再用私钥解密
message = 'hello world'
crypto = rsa.encrypt(message.encode('utf-8'), pubkey)
message = rsa.decrypt(crypto, privkey)
message = message.decode('utf-8')
print("密文: ", crypto)
print("明文: ", message)
# sign 用私钥签名认证、再用公钥验证签名
message = 'hello world'
signature = rsa.sign(message.encode('utf-8'), privkey, 'SHA-1')
method_name = rsa.verify(message.encode('utf-8'), signature, pubkey)
print(method_name)
rsa库的版本3.4是3.x范围内的最后一个版本。版本4.0删除了以下模块,因为它们不安全:rsa._version133, rsa._version200, rsa.bigfile, rsa.varblock
这些模块在3.4版中被标记为已弃用。
此外,在rsa库的版本4.0中,I / O函数经过简化,可以在所有支持的Python版本上使用字节。
4.0版本不再支持Python 2.6和3.3。
## rsa库的版本3.4下支持如下代码
from rsa.bigfile import *
import rsa
with open('public.pem') as publickfile:
p = publickfile.read()
pubkey = rsa.PublicKey.load_pkcs1(p)
with open('private.pem') as privatefile:
p = privatefile.read()
privkey = rsa.PrivateKey.load_pkcs1(p)
with open('mysec.txt', 'rb') as infile, open('outputfile', 'wb') as outfile: #加密输出
encrypt_bigfile(infile, outfile, pubkey)
with open('outputfile', 'rb') as infile2, open('result', 'wb') as outfile2: #解密输出
decrypt_bigfile(infile2, outfile2, privkey)
- 解密长度比较长的密文(分段加密):
原来加密的 plaintext 最大长度是 证书key位数/8 - 11, 例如1024 bit的证书,被加密的串最长 1024/8 - 11=117, 顺着这个思路baidu下,解决办法是分块加密,然后分块解密就行了,因为证书key固定的情况下,加密出来的串长度是固定的。
加密的字段长短规则如下:
对于 512 bit的证书,被加密的字符串的长度最长:512/8 - 11 = 53,总长度是64
对于 1024 bit的证书,被加密的字符串的长度最长:1024/8 - 11 = 117,总长度是128
对于 2048 bit的证书,被加密的字符串的长度最长:2048/8 - 11 = 245,总长度是256
解决办法是分块加密,然后分块解密就行了,
因为证书key固定的情况下,加密出来的串长度是固定的。也就是说,如果使用2048bit的证书,并且被加密的字符段是小于245个,那么被加密出来的字符长度是256个,以此类推,被加密的字符串可以是512个,1024个等。
加密使用的是公钥对数据进行加密,而且当你使用一把1024bit的rsa公钥的时候,你一次只能加密最多117byte的数据, 如果数据量超过这个数,可能会涉及到对数据进行分段加密的问题。而且现在rsa 1024bit长度的钥匙已经被证明了不够安全, 应该尽量使用2048bit长度的钥匙。2048bit长度的钥匙一次可以加密245byte长度的数据。这个计算方法是 2048bit/8 = 256byte - 11byte = 245byte长数据。就是钥匙长度减去11byte得到的自己最大能一次加密多长的数据。如果超过了就会报错, 所以很多平台要求对数据用公钥进行加密,就可能涉及到分段加密的问题。同时要注意的是,解密的时候不存在这11byte的 减少。就是说一把1024bit的钥匙可以解密128byte长的数据而2048bit的可以解密256byte的数据。
此外:加密和加签完全不是同样一件事情。
import rsa
def decrypt(encrypt_text, privkey):
s, t = 0, 128
result = []
for i in range(t, t + len(encrypt_text), t):
decrypt_text = rsa.decrypt(encrypt_text[s:i], privkey)
result.append(decrypt_text.decode('utf-8'))
s = i
return ''.join(result)
pri_pkcs8_text = '''-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIXbcicDUMXbwTQaO2z7mJ6kt+S71AO91jq0j3sN7rmtasfMo2ZRiGrZejkaNxAPSjVJ9U/8FJG7JZHE
HzOv2mtOqkSYt2Si8kofnU424jbZcxzm4zS8IeLO/FOXNYTNJ2SoJmMs1kqUZ91bzZlZ+Mh6ZReK4OcM/lJtg21MfU31AgMBAAECgYABp4avqMDU0TSAGlrlq+5k95A2
SYQDT9NYAmdLlA6BSP1q3sKePx+6glmaXxKTJj06j2FyzaDLdE6wkIX6M5A1grxeJdgn4nNFVuphoW3NZNQlKeAXzHt8d6wCvlk2HuROPCDtAIPgE9k8JOZmOM8+BJ3L
mDBmgRQ1SxgowFtheQJBAMMG42KQQ3FjoJ3QKQzMixJQ6/6Fgat7KnRb+ru/E/ueKTO0nO/JY3PZyy56t0ClPV/KVgcGFJ9j7qhJN1v+OiMCQQCvtMyZ7bHArbOPy7VX
xmYMLZI+kQChoLsmAtK9Itr6fN3EWqlWsG3Z+imFpVVkFVYNY7JZgXoZTw1ksHZAGV0HAkB+Mu7g0MlTjkxY0mI9zf4QFB0hzfJirIiEUyCkbLjZkTbIJo+G+qJITR6V
LQN36XUVjzCrytt9aIT+kKIp/RBRAkB99mijhXLkBeLvmIN13Ka13km0jvFb7cWdF3MK4p0H7FJz/ObfXfYyyZPQ2tlfuagKS0nFvvvQfwrD/3mWtFgrAkBN3xf+3JbG
2hauKJGx0yNbfCmweA3iqD7n3oml6fq7uL+pC4UXnvKtubUzVR1kJbRJAmR9YO4ucv36qKveFFoS
-----END PRIVATE KEY-----
'''
crypto_data = """
7bb70f65ec6a8e4e4f932df55f308f33a78636248dbacb76ebf88ea1cfd385e001fd36ede8ef61a1b4be44a69ad2c4d97adef8dd28c8ebfce8d0cd7a66fba772
959dab9573592182c92e2bbc89991e6a5bbca75e92ac2bbb62f1a7c13d0fedf1b9d4bb679834f6d564152cebe592a893d71c9901116a41f9f654ecb5876e1e3f
5bc696181543b86c8a2cafdb900a1c9d33841e803a0a008315aea8236cf8c9998658bb2f2699460bfbd3ee33ae94387817836213bb27f3aada76a2cb4e8fb30c
b4c778206217ac3e6ae0082b7f05d2d092c6c01c20d0f46e897f67c6f0c37abf8669efb48590ef3689ace8df063d289b27432bc2b6216113f7a5f9c901e78a7f
"""
crypto_data = bytes.fromhex(crypto_data)
pri_pkcs1_text = open(r'd:\pri_pkcs1.pem').read()
pri_pkcs1_key = rsa.PrivateKey.load_pkcs1(pri_pkcs1_text)
content = decrypt(crypto_data, pri_pkcs1_key)
print(content)
from Crypto import Random
from Crypto.PublicKey import RSA
random_generator = Random.new().read
rsa = RSA.generate(2048, random_generator)
# 生成私钥
private_key = rsa.exportKey()
print(private_key.decode('utf-8'))
# 生成公钥
public_key = rsa.publickey().exportKey()
print(public_key.decode('utf-8'))
with open('rsa_private_key.pem', 'wb')as f:
f.write(private_key)
with open('rsa_public_key.pem', 'wb')as f:
f.write(public_key)
import base64
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA
from Crypto.Signature import PKCS1_v1_5 as PKCS1_signature
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher
def get_key(key_file):
with open(key_file) as f:
data = f.read()
key = RSA.importKey(data)
return key
def encrypt_data(msg):
public_key = get_key('rsa_public_key.pem')
cipher = PKCS1_cipher.new(public_key)
encrypt_text = base64.b64encode(cipher.encrypt(bytes(msg.encode("utf8"))))
return encrypt_text.decode('utf-8')
def decrypt_data(encrypt_msg):
private_key = get_key('rsa_private_key.pem')
cipher = PKCS1_cipher.new(private_key)
back_text = cipher.decrypt(base64.b64decode(encrypt_msg), 0)
return back_text.decode('utf-8')
def test_encrypt_decrypt():
msg = "coolpython.net"
encrypt_text = encrypt_data(msg)
decrypt_text = decrypt_data(encrypt_text)
print(msg == decrypt_text)
test_encrypt_decrypt() # True
import base64
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA
from Crypto.Signature import PKCS1_v1_5 as PKCS1_signature
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher
def get_key(key_file):
with open(key_file) as f:
data = f.read()
key = RSA.importKey(data)
return key
def rsa_private_sign(data):
private_key = get_key('rsa_private_key.pem')
signer = PKCS1_signature.new(private_key)
digest = SHA.new()
digest.update(data.encode("utf8"))
sign = signer.sign(digest)
signature = base64.b64encode(sign)
signature = signature.decode('utf-8')
return signature
def rsa_public_check_sign(text, sign):
publick_key = get_key('rsa_public_key.pem')
verifier = PKCS1_signature.new(publick_key)
digest = SHA.new()
digest.update(text.encode("utf8"))
return verifier.verify(digest, base64.b64decode(sign))
def test_sign():
msg = 'hello world'
sign = rsa_private_sign(msg)
print(rsa_public_check_sign(msg, sign)) # True
if __name__ == '__main__':
test_sign()
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.Signature import PKCS1_v1_5
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
import Crypto.Util.number
import base64
class RsaUtil:
def __init__(self, pub_key, pri_key):
self.pri_key_obj = None
self.pub_key_obj = None
self.verifier = None
self.signer = None
if pub_key:
pub_key = RSA.importKey(base64.b64decode(pub_key))
self.pub_key_obj = Cipher_pkcs1_v1_5.new(pub_key)
self.verifier = PKCS1_v1_5.new(pub_key)
if pri_key:
pri_key = RSA.importKey(base64.b64decode(pri_key))
self.pri_key_obj = Cipher_pkcs1_v1_5.new(pri_key)
self.signer = PKCS1_v1_5.new(pri_key)
self.key_length = Crypto.Util.number.size(pri_key.n)
print("key_length:", self.key_length)
self.maxtext_length = int(self.key_length/8)
print("maxtext_length:", self.maxtext_length)
def public_long_encrypt(self, data, charset='utf-8'):
data = data.encode(charset)
length = len(data)
default_length = self.maxtext_length - 11
res = []
for i in range(0, length, default_length):
res.append(self.pub_key_obj.encrypt(data[i:i + default_length]))
byte_data = b''.join(res)
return base64.b64encode(byte_data)
def private_long_decrypt(self, data, sentinel=b'decrypt error'):
data = base64.b64decode(data)
length = len(data)
default_length = self.maxtext_length
res = []
for i in range(0, length, default_length):
res.append(self.pri_key_obj.decrypt(data[i:i + default_length], sentinel))
return str(b''.join(res), encoding = "utf-8")
def sign(self, data, charset='utf-8'):
h = SHA256.new(data.encode(charset))
signature = self.signer.sign(h)
return base64.b64encode(signature)
def verify(self, data, sign, charset='utf-8'):
h = SHA256.new(data.encode(charset))
return self.verifier.verify(h, base64.b64decode(sign))
if __name__ == '__main__':
pub_key = '''
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQFA4YVQZatJAyO7TsuzkWE8dz
17qi8GuOCnegKbKd6alLXkDzKhVG3kd3GijouHtlqsm2zFCK7K+I5MUu8Fuk23OE
wIVZn9StltjLzJ1hB1AZC1/NCoCFZG5T2+AaQolrw8LvPS5jH2TuYQf7oLDHR88B
KJgV/tZlr22Jicqm0wIDAQAB
'''
pri_key = '''
MIICWwIBAAKBgQCQFA4YVQZatJAyO7TsuzkWE8dz17qi8GuOCnegKbKd6alLXkDz
KhVG3kd3GijouHtlqsm2zFCK7K+I5MUu8Fuk23OEwIVZn9StltjLzJ1hB1AZC1/N
CoCFZG5T2+AaQolrw8LvPS5jH2TuYQf7oLDHR88BKJgV/tZlr22Jicqm0wIDAQAB
AoGAMP6A5IlVRdcNCef/2Fi6SuWi96OuleYHzR+GGnLTiJuCtFxy3b27yoOf7cJ5
ktnZLHNtcLn90aA2+OhCnXmiz+M9PNArzfvtDoAKMlM9UEpBjGW/QYPkcHgnKOs9
utAr4OnPB9PFdvCuwya4P8AL/7kpjSW+4zQpUT459BlJFxECQQDYUnQQgyR3CZiG
Pj9vPfmmFmogpZpJTG9zAuOjOCxa5BQvV4iKhk6pkQAaVsjc7WMobEIhLqXn/I8E
ldsqIPj1AkEAqoFZULpjke8CQm0rmr2UdbhU74KKYzeS2KKKc/2TdQUzTqvBdY2+
VCyc0Ok6BWctBHfsu4FR6YpDYsg3QwvjpwJAEHeuaDdjhkBPwSBp+dDw+UjJiXSx
2xSbg1jb9WfoUH7+XmA+f7UbteLY7ChhIBheLQyYuCfx70gVpxa1WW6rJQJAEahR
mpWi6CMLZduub1kAvew4B5HKSRohQAQdOIPjOHQwaw5Ie6cRNeBk4RG2K4cS12qf
/o8W74udDObVKkFZ8wJAPL8bRWv0IWTlvwM14mKxcVf1qCuhkT8GgrG/YP/8fcW8
SiT+DifcA7BVOgQjgbTchSfaA+YNe7A9qiVmA+G4GQ==
'''
data = "hello world"
rsa_util = RsaUtil(pub_key, pri_key)
print(f'原文: {data}')
encrypt = rsa_util.public_long_encrypt(data)
print(f'加密: {encrypt}')
decrypt_str = rsa_util.private_long_decrypt(encrypt)
print(f'解密: {decrypt_str}')
sign = rsa_util.sign(data)
print(f'sign: {sign}')
verify = rsa_util.verify(decrypt_str, sign)
print(f'verify: {verify}')
# coding=utf-8
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA
def read_private_key(key_file=None):
key = key_file and open(key_file).read()
if not key:
key = '''-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIXbcicDUMXbwTQaO2z7mJ6kt+S71AO91jq0j3sN7rmtasfMo2ZRiGrZejkaNxAPSjVJ9U/8FJG7JZHE
HzOv2mtOqkSYt2Si8kofnU424jbZcxzm4zS8IeLO/FOXNYTNJ2SoJmMs1kqUZ91bzZlZ+Mh6ZReK4OcM/lJtg21MfU31AgMBAAECgYABp4avqMDU0TSAGlrlq+5k95A2
SYQDT9NYAmdLlA6BSP1q3sKePx+6glmaXxKTJj06j2FyzaDLdE6wkIX6M5A1grxeJdgn4nNFVuphoW3NZNQlKeAXzHt8d6wCvlk2HuROPCDtAIPgE9k8JOZmOM8+BJ3L
mDBmgRQ1SxgowFtheQJBAMMG42KQQ3FjoJ3QKQzMixJQ6/6Fgat7KnRb+ru/E/ueKTO0nO/JY3PZyy56t0ClPV/KVgcGFJ9j7qhJN1v+OiMCQQCvtMyZ7bHArbOPy7VX
xmYMLZI+kQChoLsmAtK9Itr6fN3EWqlWsG3Z+imFpVVkFVYNY7JZgXoZTw1ksHZAGV0HAkB+Mu7g0MlTjkxY0mI9zf4QFB0hzfJirIiEUyCkbLjZkTbIJo+G+qJITR6V
LQN36XUVjzCrytt9aIT+kKIp/RBRAkB99mijhXLkBeLvmIN13Ka13km0jvFb7cWdF3MK4p0H7FJz/ObfXfYyyZPQ2tlfuagKS0nFvvvQfwrD/3mWtFgrAkBN3xf+3JbG
2hauKJGx0yNbfCmweA3iqD7n3oml6fq7uL+pC4UXnvKtubUzVR1kJbRJAmR9YO4ucv36qKveFFoS
-----END PRIVATE KEY-----
'''
return RSA.importKey(key)
def cipher_pksc1(rsakey=read_private_key()):
return PKCS1_v1_5.new(rsakey)
def decrypt(encrypt_text, cipher=cipher_pksc1(), sentinel=None):
s, t = 0, 128
result = []
for i in range(t, t + len(encrypt_text), t):
decrypt_text = cipher.decrypt(encrypt_text[s:i], sentinel)
result.append(decrypt_text.decode('utf-8'))
s = i
return ''.join(result)
def main():
crypto_data = """
7bb70f65ec6a8e4e4f932df55f308f33a78636248dbacb76ebf88ea1cfd385e001fd36ede8ef61a1b4be44a69ad2c4d97adef8dd28c8ebfce8d0cd7a66fba772
959dab9573592182c92e2bbc89991e6a5bbca75e92ac2bbb62f1a7c13d0fedf1b9d4bb679834f6d564152cebe592a893d71c9901116a41f9f654ecb5876e1e3f
5bc696181543b86c8a2cafdb900a1c9d33841e803a0a008315aea8236cf8c9998658bb2f2699460bfbd3ee33ae94387817836213bb27f3aada76a2cb4e8fb30c
b4c778206217ac3e6ae0082b7f05d2d092c6c01c20d0f46e897f67c6f0c37abf8669efb48590ef3689ace8df063d289b27432bc2b6216113f7a5f9c901e78a7f
"""
crypto_data = bytes.fromhex(crypto_data )
# print(crypto_data )
print('当前密文长度:', len(crypto_data ))
print(decrypt(crypto_data ))
if __name__ == '__main__':
main()