【小沐学python】(二)Python常见问题汇总

🍺小沐学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代码的执行方式有两种:

  • 命令行执行方式
  • 脚本代码执行方式

1.3 查看库的版本

  • 方法1
    能够列出当前版本的Python支持的所有第三方库的版本
pip install flask==

在这里插入图片描述

  • 方法2
https://pypi.python.org/simple/ + 第三方包名
https://pypi.org/simple/django
https://pypi.org/simple/flask

浏览器访问如下:
在这里插入图片描述

  • 方法3
import requests
r = requests.get("https://pypi.org/pypi/Flask/json")
print(r.json()['releases'].keys())

在这里插入图片描述

import json
import urllib.request
from distutils.version import StrictVersion

# print PyPI versions of package
def versions(package_name):
    url = "https://pypi.org/pypi/%s/json" % (package_name,)
    data = json.load(urllib.request.urlopen(url))
    versions = list(data["releases"])
    sortfunc = lambda x: StrictVersion(x.replace('rc', 'b').translate(str.maketrans('cdefghijklmn', 'bbbbbbbbbbbb')))
    versions.sort(key=sortfunc)
    return versions
    
print("\n".join(versions("flask")))

在这里插入图片描述

#!/usr/bin/env python3

import json
import sys
from urllib import request    
from pkg_resources import parse_version    

def versions(pkg_name):
    url = f'https://pypi.org/pypi/{pkg_name}/json'
    releases = json.loads(request.urlopen(url).read())['releases']
    return sorted(releases, key=parse_version, reverse=True)    

if __name__ == '__main__':
    # print(*versions(sys.argv[1]), sep='\n')
    print(*versions("flask"), sep=', ')

在这里插入图片描述

  • 方法4
pip install yolk3k

在这里插入图片描述

# show available versions for given package listed on PyPI
yolk -V flask

在这里插入图片描述

#  show dependencies for a package installed by setuptools if they are available
yolk -d flask

在这里插入图片描述

#  show metadata for a package listed on PyPI. Use -f to show particular fields
yolk -M flask

在这里插入图片描述

1.4 导入导出离线包

  • (1)导出文件requirements.txt
pip freeze > requirements.txt
virtualenv myenv
cd test
pip install -r requirements.txt
  • (2)离线包下载
pip download -d PIPDIR -r requirements.txt -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com 
pip download -r requirements.txt
pip download flask -d D:/pkg
pip download -d /tmp/packagesdir <packagename>
pip download -d /tmp/packagesdir -r requirements.txt

-d指定导出的文件夹
-r指定根据哪一个文件导出
-i表示使用阿里源(当然可以使用其他国内源啊)
–trusted-host表示信任主机
https://pip.pypa.io/en/stable/cli/pip_download/#options

在这里插入图片描述

  • (3)离线包安装
pip install --no-index --find-links=PIPDIR -r requirements.txt
pip install --no-index --find-links="." -r requirements.txt
pip install --no-index -f=<目录>/ <包名>
pip install --no-index --use-wheel --find-links=wheelhouse/ <包名>
pip install <目录>/<文件名>

–find-links就是存放安装文件的目录
-r是指按照requirements.txt这个文件去安装文件目录中找需要的安装包

  • (4)手动下载和安装
    python库的whl文件下载地址:
    https://pypi.org/ 或者https://www.lfd.uci.edu/~gohlke/pythonlibs/
pip install c:\numpy‑1.18.1 + mkl‑cp38‑cp38‑win_amd64.whl
pip install PyMySQL-0.9.3-py2.py3-none-any.whl

常见的安装方法:
直接在 pypi 官网下载,而后进行手动安装
使用 pip 根据requirements文件下载安装包,到离线环境中再使用 pip 安装
通过docker 安装相应环境,
通过 Ansible 自动化部署,

1.5 各种版本

1.5.1 CPython

https://github.com/python/cpython

The Python programming language

在这里插入图片描述
CPython是Python语言的一种实现,是用C语言开发的解释器。Python语言有多种实现,除了CPython,还有PyPy(使用Python)、Jython(使用Java)等。CPython是目前应用最广泛的解释器,也是Python的官方实现。

1.5.2 ironPython

https://github.com/IronLanguages/ironpython3
https://ironpython.net/

IronPython 与 Jython 类似,它是 .NET 框架的 python 实现

在这里插入图片描述
IronPython 是 Python 编程语言的开源实现,与 .NET 紧密集成。IronPython 可以使用 .NET 和 Python 库,其他 .NET 语言也可以同样轻松地使用 Python 代码。

IronPython 是 .NET 的一个很好的补充,提供了 Python 借助 .NET 的强大功能的开发人员。现有的 .NET 开发人员可以 还使用 IronPython 作为快速且富有表现力的脚本语言进行嵌入, 测试,或从头开始编写新应用程序。

CLR 是创建编程语言的绝佳平台,而 DLR 使动态语言变得更好。此外,.NET (基类库、表示基础等)给出 开发人员拥有惊人的功能和功能。

import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import MessageBox, MessageBoxButtons

MessageBox.Show("Hello World!", "Greetings", MessageBoxButtons.OKCancel)

1.5.3 Jython

https://www.jython.org/

Jython(Java Python 的缩写)由 Java 编写,运行在 Java 虚拟机上( Java Virtual Machine,JVM)

在这里插入图片描述
Jython 项目提供了 Java 中 Python 的实现, 为 Python 提供在 JVM 上运行的好处,并访问用 Java 编写的类。 当前发行版(Jython 2.7.x)仅支持 Python 2(对不起)。 该项目的 GitHub 存储库中正在开发 Python 3。

Jython 实现可免费用于商业和非商业用途。 它们根据 PSF 许可证 v2 与源代码一起分发。

from java.lang import System # Java import

print('Running on Java version: ' + System.getProperty('java.version'))
print('Unix time from Java: ' + str(System.currentTimeMillis()))

1.5.4 micropython

https://micropython.org/

MicroPython 可在各种系统和硬件平台上运行。只包含了 python 标准库中的一小部分并经过优化,以适应资源受限的环境,专为嵌入式系统和物联网设备而设计。

在这里插入图片描述
MicroPython 是 Python 3 编程语言的精益高效实现 它包括 Python 标准库的一小部分,并且是 经过优化,可在微控制器和受限环境中运行。

MicroPython pyboard 是一个紧凑的电子 在裸机上运行 MicroPython 的电路板,为您提供低级 可用于控制各种电子的Python操作系统 项目。

MicroPython 包含许多高级功能,例如交互式 提示、任意精度整数、闭包、列表推导、 生成器、异常处理等。然而,它足够紧凑,可以容纳和 在仅 256k 的代码空间和 16k 的 RAM 内运行。

1.5.5 Pypy

https://www.pypy.org/index.html

A fast, compliant alternative implementation of Python

在这里插入图片描述
Pypy 是最著名的 CPython 替代品,它是用 python 编写的。
Pypy 实际上是由 RPython 实现的,RPython 是 Python 的一个子集。
Pypy 使用即时编译(JIT)技术,可以在运行时将 Python 代码动态地编译成机器码,从而提供更高的执行速度。
Pypy 使用它的主要原因 速度代替了 CPython:它通常运行得更快。

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 是尾数,7 是指数。

(3)复数类型

复数(Complex)是 Python 的内置类型,直接书写即可。

(4)字符串类型

若干个字符的集合就是一个字符串(String)。Python 中的字符串必须由双引号" "或者单引号’ '包围。

(5)布尔类型

Python 提供了 bool 类型来表示真(对)或假(错),True 和 False 是 Python 中的关键字,当作为 Python 代码输入时,一定要注意字母的大小写,否则解释器会报错。

2.4 运算符

  1. 算术运算符
  2. 比较(关系)运算符
  3. 赋值运算符
  4. 逻辑运算符
  5. 位运算符
  6. 成员运算符
  7. 身份运算符

2.4.1 if

  • 写法1:
def even_parity(bit_string):
    num = bit_string.count("1") % 2
    end_str = "0" if num % 2 == 0 else "1"
    return bit_string + end_str

if __name__ == '__main__':
    bit_string = "1100001"
    print("{} --Even Parity--> {}".format(bit_string, even_parity(bit_string)))

    bit_string = "1100000"
    print("{} --Even Parity--> {}".format(bit_string, even_parity(bit_string)))

2.4.2 format

  • 写法2:
    print语句中加入f就可以起到和format函数类似的作用。
def even_parity(bit_string):
    return bit_string + str(bit_string.count("1") % 2)

if __name__ == '__main__':
    bit_string = "1100001"
    print(f"{bit_string} --Even Parity--> {even_parity(bit_string)}")

    bit_string = "1100000"
    print(f"{bit_string} --Even Parity--> {even_parity(bit_string)}")

2.4.3 Lambda

  • 为何使用 Lambda 函数?
    当您把 lambda 用作另一个函数内的匿名函数时,会更好地展现 lambda 的强大能力。
    假设您有一个带一个参数的函数定义,并且该参数将乘以未知数字:
## 1
x = lambda a : a + 10
print(x(5))

## 2
def myfunc(n):
  return lambda a : a * n

mydoubler = myfunc(2)
mytripler = myfunc(3)

print(mydoubler(11)) 
print(mytripler(11))

2.4.4 map

map() 会根据提供的函数对指定序列做映射。
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。

def square(x) :            # 计算平方数
    return x ** 2

map(square, [1,2,3,4,5]) #Python2.x 
## [1, 4, 9, 16, 25]

list(map(square, [1,2,3,4,5])) #Python3.x 
## [1, 4, 9, 16, 25]

map(lambda x: x ** 2, [1, 2, 3, 4, 5])  # 使用 lambda 匿名函数
## [1, 4, 9, 16, 25]

map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
## [3, 7, 11, 15, 19]

2.4.5 多行文本

  • 使用三引号的Python多行字符串 (Python Multiline String using triple quotes)
s = 'My Name is XiaoMu.\nI am the owner of JournalDev.com\nJournalDev is a very popular website in Developers community.'
s = """My Name is XiaoMu.
I am the owner of JournalDev.com
JournalDev is a very popular website in Developers community."""
  • 使用括号的多行字符串 (Multiline string using brackets)
s = ("My Name is XiaoMu. "
     "I am the owner of JournalDev.com and "
     "JournalDev is a very popular website in Developers community.")
print(s)
  • 使用反斜线的多行字符串 (Multiline string using backslash)
s = "My Name is XiaoMu. " \
    "I am the owner of JournalDev.com and " \
    "JournalDev is a very popular website in Developers community."
print(s)
  • 使用join()的Python多行字符串 (Python multiline string using join())
s = ' '.join(("My Name is XiaoMu. I am the owner of",
              "JournalDev.com and",
              "JournalDev is a very popular website",
              "in Developers community."))
print(s)

2.5 输入输出

  • print() 函数
    用于输出一个或多个值。
    print (value,…,sep=‘’,end=‘\n’,file=sys.stdout,flush=False)
print("读者名:" ,user_name,"年龄:",user_age,sep='|')
  • input() 函数
    用于从控制台读取用户输入的内容。
str = input("Please input:")

2.6 r’‘, b’‘, u’‘, f’’ 的含义

  • r/R:非转义的原始字符串
    与普通字符相比,其他相对特殊的字符,其中可能包含转义字符,即那些,反斜杠加上对应字母,表示对应的特殊含义的,比如最常见的”\n”表示换行,”\t”表示Tab等。而如果是以r开头,那么说明后面的字符,都是普通的字符了,即如果是“\n”那么表示一个反斜杠字符,一个字母n,而不是表示换行了。
    r’input\n’ # 非转义原生字符,经处理’\n’变成了’\‘和’n’。也就是\n表示的是两个字符,而不是换行。

  • b:bytes
    python3.x里默认的str是(py2.x里的)unicode, bytes是(py2.x)的str, b”“前缀代表的就是bytes
    python2.x里, b前缀没什么具体意义, 只是为了兼容python3.x的这种写法
    b’input\n’ # bytes字节符,打印以b开头。

  • u/U:表示unicode字符串
    不是仅仅是针对中文, 可以针对任何的字符串,代表是对字符串进行unicode编码。
    一般英文字符在使用各种编码下, 基本都可以正常解析, 所以一般不带u;但是中文, 必须表明所需编码, 否则一旦编码转换就会出现乱码。
    建议所有编码方式采用utf8.
    u’input\n’ # unicode编码字符,python3默认字符串编码方式。

  • f/format():格式化操作

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库的一些用法
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

  • 读取excel,根据条件计算某一列的值
#-- 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)
  • 将新浪数据存成csv文件和excel文件
#-- 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/releases
https://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.html
https://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.html
https://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/

pip install PySide2

PySide2 是来自 Qt for Python 项目的官方 Python 模块,它提供对完整 Qt 5.12+ 框架的访问。

Qt for Python 项目是开放式开发的,具有您期望从任何现代 OSS 项目中获得的所有功能,例如 git 存储库中的所有代码和开放式设计过程。我们欢迎任何符合 Qt 贡献协议的贡献。

  • PySide2例子一
import sys
from PySide2.QtWidgets import QApplication, QPushButton

app = QApplication(sys.argv)

window = QPushButton("Push Me")
window.show()

app.exec_()

在这里插入图片描述

  • PySide2例子二

#!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/

pip install pyqt5-tools

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这种格式。
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple rsa
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
  • rsa库的加密和解密代码
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 msg
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)
  • (2)Crypto库
  • 安装Crypto库如下:
pip install pycryptodome
  • 直接生成私钥和公钥
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))    # Trueif __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()

结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)
感谢各位大佬童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值