Files
python-flask/project8/01.常用模块.md
2025-09-11 16:13:52 +08:00

665 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 序列化相关模块
将原本的字典、列表等内容转换成一个字符串的过程就叫做**序列化**
**序列化的目的**
1. 以某种存储形式使自定义对象持久化;
2. 将对象从一个地方传递到另一个地方。
3. 使程序更具维护性。
<img src="./01.常用模块/image-20241018165407028.png" alt="image-20241018165407028" style="zoom: 80%;" />
python可序列化的数据类型序列化出来之后的结果如下:
| Python | JSON |
| ---------- | ------ |
| dict | object |
| list,tuple | array |
| str | string |
| int,float | number |
| True | true |
| False | false |
| None | null |
## json模块
Python 的 `json` 模块用于处理 JSONJavaScript Object Notation数据格式。JSON 是一种轻量级的数据交换格式,易于人类阅读和编写,同时也易于机器解析和生成。`json` 模块提供了简单的方法来编码序列化和解码反序列化JSON数据。
### 常用功能
1. **序列化**:将 Python 数据类型转换为 JSON 格式。
2. **反序列化**:将 JSON 格式的数据转换为 Python 数据类型。
### 基本用法
1. **导入模块**
首先需要导入 `json` 模块:
```python
import json
```
2. **序列化 Python 对象为 JSON 字符串**
使用 `json.dumps()` 方法将 Python 对象转换为 JSON 字符串。
```python
data = {
"name": "Alice",
"age": 30,
"is_student": False,
"courses": ["Math", "Science"]
}
json_string = json.dumps(data)
print(json_string)
```
输出:
```json
{"name": "Alice", "age": 30, "is_student": false, "courses": ["Math", "Science"]}
```
3. **反序列化 JSON 字符串为 Python 对象**
使用 `json.loads()` 方法将 JSON 字符串转换为 Python 对象。
```python
json_string = '{"name": "Alice", "age": 30, "is_student": false, "courses": ["Math", "Science"]}'
data = json.loads(json_string)
print(data)
print(data['name']) # 访问字典中的值
```
输出:
```json
{'name': 'Alice', 'age': 30, 'is_student': False, 'courses': ['Math', 'Science']}
Alice
```
4. **从文件读取 JSON 数据**
使用 `json.load()` 方法从文件中读取 JSON 数据并转换为 Python 对象。
```python
# 假设 json_data.json 文件内容是上面的 JSON 字符串
with open('json_data.json', 'r') as file:
data = json.load(file)
print(data)
```
5. **将 Python 对象写入 JSON 文件**
使用 `json.dump()` 方法将 Python 对象写入 JSON 文件。
```python
data = {
"name": "Bob",
"age": 25,
"is_student": True,
"courses": ["English", "History"]
}
with open('output.json', 'w') as file:
json.dump(data, file)
```
### 自定义序列化
可以通过自定义函数来处理复杂对象。
| 属性名 | 描述 |
| :----------- | :----------------------------------------------------------- |
| Skipkeys | 1,默认值是False如果dict的keys内的数据不是python的基本类型,2,设置为False时就会报TypeError的错误。此时设置成True则会跳过这类key3,当它为True的时候所有非ASCII码字符显示为\uXXXX序列只需在dump时将ensure_ascii设置为False即可此时存入json的中文即可正常显示。 |
| indent | 是一个非负的整型如果是0就是顶格分行显示如果为空就是一行最紧凑显示否则会换行且按照indent的数值显示前面的空白分行显示这样打印出来的json数据也叫pretty-printed json |
| ensure_ascii | 当它为True的时候所有非ASCII码字符显示为\uXXXX序列只需在dump时将ensure_ascii设置为False即可此时存入json的中文即可正常显示。 |
| separators | 分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(,,:)这表示dictionary内keys之间用“,”隔开而KEY和value之间用“”隔开。 |
| sort_keys | 将数据根据keys的值进行排序 |
```python
import json
data = {'name': 'Alice', 'age': 30, 'is_student': False, 'courses': ['Math', 'Science']}
json_dic2 = json.dumps(data,sort_keys=True,indent=2,separators=(',',':'),ensure_ascii=False)
print(json_dic2)
```
输出:
```json
{
"age":30,
"courses":[
"Math",
"Science"
],
"is_student":false,
"name":"Alice"
}
```
## hashlib模块
Python 的 `hashlib` 模块提供了多种安全哈希和消息摘要算法的接口。这些算法用于生成数据的唯一哈希值,广泛应用于数据完整性校验、密码存储和数字签名等领域。
什么是摘要算法呢摘要算法又称哈希算法、散列算法。它通过一个函数把任意长度的数据转换为一个长度固定的数据串通常用16进制的字符串表示
摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest目的是为了发现原始数据是否被人篡改过。
摘要算法之所以能指出数据是否被篡改过就是因为摘要函数是一个单向函数计算f(data)很容易但通过digest反推data却非常困难。而且对原始数据做一个bit的修改都会导致计算出的摘要完全不同。
`hashlib` 支持多种哈希算法,包括:
- MD5
- SHA-1
- SHA-224
- SHA-256
- SHA-384
- SHA-512
- BLAKE2
### 基本用法
1. **导入模块**
首先需要导入 `hashlib` 模块:
```python
import hashlib
```
2. **创建哈希对象**
可以使用不同的算法创建哈希对象。以下是一些常见算法的示例:
```python
# 创建一个 SHA-256 哈希对象
sha256_hash = hashlib.sha256()
# 创建一个 MD5 哈希对象
md5_hash = hashlib.md5()
```
3. **更新哈希对象**
使用 `update()` 方法将数据传递给哈希对象。可以多次调用 `update()` 方法以添加更多数据。
```python
data = b"Hello, World!"
sha256_hash.update(data)
md5_hash.update(data)
```
4. **获取哈希值**
使用 `hexdigest()` 方法获取哈希值的十六进制字符串表示。
```python
sha256_digest = sha256_hash.hexdigest()
md5_digest = md5_hash.hexdigest()
print("SHA-256:", sha256_digest)
print("MD5:", md5_digest)
```
### 完整示例
以下是一个完整的示例,展示了如何使用 `hashlib` 模块:
```python
import hashlib
# 要哈希的数据
data = b"Hello, World!"
# 使用 SHA-256 算法
sha256_hash = hashlib.sha256()
sha256_hash.update(data)
print("SHA-256:", sha256_hash.hexdigest())
# 使用 MD5 算法
md5_hash = hashlib.md5()
md5_hash.update(data)
print("MD5:", md5_hash.hexdigest())
# 使用 SHA-512 算法
sha512_hash = hashlib.sha512()
sha512_hash.update(data)
print("SHA-512:", sha512_hash.hexdigest())
```
### 注意事项
1. **不可逆性**:哈希函数是不可逆的,意味着无法从哈希值恢复原始数据。
2. **碰撞**:不同的输入可能生成相同的哈希值(称为碰撞),但现代的哈希算法力求使碰撞的概率尽量低。
3. **安全性**:对于密码存储,建议使用更安全的哈希算法(如 SHA-256 或更高版本和适当的盐值salt来增强安全性。
### 使用场景
- **数据完整性**:用于验证文件或数据在传输过程中未被篡改。
- **密码存储**:将用户密码的哈希值存储在数据库中,而不是明文密码。
- **数字签名**:用于创建数字签名,确保数据来源的可靠性。
任何允许用户登录的网站都会存储用户登录的用户名和口令。如何存储用户名和口令呢?方法是存到数据库表中
```sql
name | password
--------+----------
michael | 123456
bob | abc999
alice | alice2008
```
如果使用md5来将保护密码那么就是这样
```sql
username | password
---------+---------------------------------
michael | e10adc3949ba59abbe56e057f20f883e
bob | 878ef96e86145580c38c87f0410ad153
alice | 99b1c2188db85afee403b1536010c2c9
```
有很多md5撞库工具可以轻松的将简单密码给碰撞出来
所以要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5这一方法通过对原始口令加一个复杂字符串来实现俗称“加盐”
# 时间相关的模块
## time模块
常用方法
- time.sleep(secs)
- (线程)推迟指定的时间运行。单位为秒。
- time.time()
- 获取当前时间戳
表示时间的三种方式
在Python中通常有这三种方式来表示时间时间戳、结构化的时间(struct_time)、格式化的时间字符串(Format String)
1. **时间戳**(timestamp) 通常来说时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”返回的是float类型。
2. 格式化的时间字符串(Format String) 1999-12-06
| %y | 两位数的年份表示00-99 |
| ---- | :---------------------------------------- |
| %Y | 四位数的年份表示000-9999 |
| %m | 月份01-12 |
| %d | 月内中的一天0-31 |
| %H | 24小时制小时数0-23 |
| %I | 12小时制小时数01-12 |
| %M | 分钟数00=59 |
| %S | 秒00-59 |
| %a | 本地简化星期名称 |
| %A | 本地完整星期名称 |
| %b | 本地简化的月份名称 |
| %B | 本地完整的月份名称 |
| %c | 本地相应的日期表示和时间表示 |
| %j | 年内的一天001-366 |
| %p | 本地A.M.或P.M.的等价符 |
| %U | 一年中的星期数00-53星期天为星期的开始 |
| %w | 星期0-6星期天为星期的开始 |
| %W | 一年中的星期数00-53星期一为星期的开始 |
| %x | 本地相应的日期表示 |
| %X | 本地相应的时间表示 |
| %Z | 当前时区的名称 |
| %% | %号本身 |
3. 结构化时间(struct_time) struct_time结构化时间共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)
| 索引Index | 属性Attribute | 值Values |
| :------------ | :------------------------ | :----------------- |
| 0 | tm_year | 比如2011 |
| 1 | tm_mon | 1月12日 |
| 2 | tm_mday | 1月31日 |
| 3 | tm_hour | 0 - 23 |
| 4 | tm_min | 0 - 59 |
| 5 | tm_sec | 0 - 60 |
| 6 | tm_wdayweekday | 0 - 60表示周一 |
| 7 | tm_yday一年中的第几天 | 1 - 366 |
| 8 | tm_isdst是否是夏令时 | 默认为0 |
```python
import time
# 第一种时间格式,时间戳的形式
print(time.time())
# 第二种时间格式,格式化的时间
print(time.strftime('%Y-%m-%d %X'))
print(time.strftime('%Y-%m-%d %H-%M-%S'))
# 第三种时间格式,结构化的时间,是一个元组
print(time.localtime())
```
小结:时间戳是计算机能够识别的时间;时间字符串是人能够看懂的时间;结构化时间则是用来操作时间的
**几种格式之间的转换**
<img src="./01.常用模块/987936105.png" alt="img" style="zoom:80%;" />
```python
import time
# 格式化时间 ----> 结构化时间
ft = time.strftime('%Y/%m/%d %H:%M:%S')
st = time.strptime(ft,'%Y/%m/%d %H:%M:%S')
print(st)
# 结构化时间 ---> 时间戳
t = time.mktime(st)
print(t)
# 时间戳 ----> 结构化时间
t = time.time()
st = time.localtime(t)
print(st)
# 结构化时间 ---> 格式化时间
ft = time.strftime('%Y/%m/%d %H:%M:%S',st)
print(ft)
```
<img src="./01.常用模块/838049513.png" alt="img" style="zoom:80%;" />
```python
import time
#结构化时间 --> %a %b %d %H:%M:%S %Y串
#time.asctime(结构化时间) 如果不传参数,直接返回当前时间的格式化串
print(time.asctime(time.localtime(1550312090.4021888)))
#时间戳 --> %a %d %d %H:%M:%S %Y串
#time.ctime(时间戳) 如果不传参数,直接返回当前时间的格式化串
print(time.ctime(1550312090.4021888))
```
计算时间差
```python
import time
start_time=time.mktime(time.strptime('2017-09-11 08:30:00','%Y-%m-%d %H:%M:%S'))
end_time=time.mktime(time.strptime('2024-10-12 11:00:50','%Y-%m-%d %H:%M:%S'))
dif_time=end_time-start_time
struct_time=time.gmtime(dif_time)
print('过去了%d%d%d%d小时%d分钟%d秒'%(struct_time.tm_year-1970,struct_time.tm_mon-1,
struct_time.tm_mday-1,struct_time.tm_hour,
struct_time.tm_min,struct_time.tm_sec))
```
## datatime模块
某些情况下我们需要写一个定时的任务比如几分钟后几分钟前这种情况下用time模块就不太好操作。这个时候我们需要datatime模块来完成这个操作
```python
# datatime模块
import datetime
now_time = datetime.datetime.now() # 现在的时间
# 只能调整的字段weeks days hours minutes seconds
print(datetime.datetime.now() + datetime.timedelta(weeks=3)) # 三周后
print(datetime.datetime.now() + datetime.timedelta(weeks=-3)) # 三周前
print(datetime.datetime.now() + datetime.timedelta(days=-3)) # 三天前
print(datetime.datetime.now() + datetime.timedelta(days=3)) # 三天后
print(datetime.datetime.now() + datetime.timedelta(hours=5)) # 5小时后
print(datetime.datetime.now() + datetime.timedelta(hours=-5)) # 5小时前
print(datetime.datetime.now() + datetime.timedelta(minutes=-15)) # 15分钟前
print(datetime.datetime.now() + datetime.timedelta(minutes=15)) # 15分钟后
print(datetime.datetime.now() + datetime.timedelta(seconds=-70)) # 70秒前
print(datetime.datetime.now() + datetime.timedelta(seconds=70)) # 70秒后
current_time = datetime.datetime.now()
# 可直接调整到指定的 年 月 日 时 分 秒 等
print(current_time.replace(year=1977)) # 直接调整到1977年
print(current_time.replace(month=1)) # 直接调整到1月份
print(current_time.replace(year=1989,month=4,day=25)) # 1989-04-25 18:49:05.898601
# 将时间戳转化成时间
print(datetime.date.fromtimestamp(1232132131)) # 2009-01-17
```
# random模块
用来生成随机数模块
```python
import random
print(random.random()) # 大于0且小于1之间的小数
print(random.uniform(1,3)) # 大于1小于3的小数
print(random.randint(1,5)) # 大于等于1且小于等于5之间的整数
print(random.randrange(1,10,2)) # 大于等于1且小于10之间的奇数
ret = random.choice([1,'23',[4,5]]) # 1或者23或者[4,5]
print(ret)
a,b = random.sample([1,'23',[4,5]],2) # 列表元素任意2个组合
print(a,b)
item = [1,3,5,7,9]
random.shuffle(item) # 打乱次序
print(item)
```
生成随机验证码
```python
import random
def v_code():
code = ''
for i in range(5):
num=random.randint(0,9)
alf=chr(random.randint(65,90))
add=random.choice([num,alf])
code="".join([code,str(add)])
return code
print(v_code())
```
# OS模块
os模块是与操作系统交互的一个接口
当前执行这个python文件的工作目录相关的**工作路径**
| 方法 | 描述 |
| :------------------ | :----------------------------------------------- |
| os.getcwd() | 获取当前工作目录即当前python脚本工作的目录路径 |
| os.chdir("dirname") | 改变当前脚本工作目录相当于shell下cd |
| os.curdir | 返回当前目录: ('.') |
| os.pardir | 获取当前目录的父目录字符串名:('..') |
**文件夹相关**
| 方法 | 描述 |
| :------------------------------- | :----------------------------------------------------------- |
| os.makedirs('dirname1/dirname2') | 可生成多层递归目录 |
| os.removedirs('dirname1') | 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 |
| os.mkdir('dirname') | 生成单级目录相当于shell中mkdir dirname |
| os.rmdir('dirname') | 删除单级空目录若目录不为空则无法删除报错相当于shell中rmdir dirname |
| os.listdir('dirname') | 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 |
**文件相关**
| 方法 | 描述 |
| :----------------------------- | :---------------- |
| os.remove() | 删除一个文件 |
| os.rename("oldname","newname") | 重命名文件/目录 |
| os.stat('path/filename') | 获取文件/目录信息 |
操作系统差异相关
| 方法 | 描述 |
| :--------- | :------------------------------------------------------ |
| os.sep | 输出操作系统特定的路径分隔符win下为"\\\",Linux下为"/" |
| os.linesep | 输出当前平台使用的行终止符win下为"\t\n",Linux下为"\n" |
| os.pathsep | 输出用于分割文件路径的字符串 win下为;,Linux下为: |
| os.name | 输出字符串指示当前使用平台。win->'nt'; Linux->'posix' |
执**行系统命令相关**
| 方法 | 描述 |
| :----------------------------- | :-------------------------- |
| os.system("bash command") | 运行shell命令直接显示 |
| os.popen("bash command).read() | 运行shell命令获取执行结果 |
| os.environ | 获取系统环境变量 |
**path系列和路径相关**
| 方法 | 描述 |
| :---------------------------------- | :----------------------------------------------------------- |
| os.path.abspath(path) | 返回path规范化的绝对路径 |
| os.path.split(path) | 将path分割成目录和文件名二元组返回 |
| os.path.dirname(path) | 返回path的目录。其实就是os.path.split(path)的第一个元素 |
| os.path.basename(path) | 返回path最后的文件名。如何path以或\结尾那么就会返回空值即os.path.split(path)的第二个元素。 |
| os.path.exists(path) | 如果path存在返回True如果path不存在返回False |
| os.path.isabs(path) | 如果path是绝对路径返回True |
| os.path.isfile(path) | 如果path是一个存在的文件返回True。否则返回False |
| os.path.isdir(path) | 如果path是一个存在的目录则返回True。否则返回False |
| os.path.join(path1[, path2[, ...]]) | 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 |
| os.path.getatime(path) | 返回path所指向的文件或者目录的最后访问时间 |
| os.path.getmtime(path) | 返回path所指向的文件或者目录的最后修改时间 |
| os.path.getsize(path) | 返回path的大小 |
```python
import os
print(os.stat('.\diary.txt')) # 当前目录下的diary文件的信息
# Output:
os.stat_result(st_mode=33206, st_ino=36310271995704245, st_dev=2088613962, st_nlink=1, st_uid=0, st_gid=0, st_size=11, st_atime=1725502765, st_mtime=1725502764, st_ctime=1725502759)
```
| 方法 | 描述 |
| :------- | :----------------------------------------------------------- |
| st_mode | inode 保护模式 |
| st_ino | inode 节点号 |
| st_dev | inode 驻留的设备 |
| st_nlink | inode 的链接数 |
| st_uid | 所有者的用户ID |
| st_gid | 所有者的组ID |
| st_size | 普通文件以字节为单位的大小;包含等待某些特殊文件的数据 |
| st_atime | 上次访问的时间 |
| st_mtime | 最后一次修改的时间 |
| st_ctime | 由操作系统报告的"ctime"。在某些系统上如Unix是最新的元数据更改的时间在其它系统上如Windows是创建时间详细信息参见平台的文档 |
# sys模块
sys模块是与python解释器交互的一个接口
| 方法 | 描述 |
| :----------- | :----------------------------------------------------- |
| sys.argv | 命令行参数List第一个元素是程序本身路径 |
| sys.exit(n) | 退出程序正常退出时exit(0),错误退出sys.exit(1) |
| sys.version | 获取Python解释程序的版本信息 |
| sys.path | 返回模块的搜索路径初始化时使用PYTHONPATH环境变量的值 |
| sys.platform | 返回操作系统平台名称 |
# shutil模块
`shutil` 是 Python 的标准库之一,提供了许多高级文件操作,例如复制和移动文件,以及创建和提取压缩文件
可以理解为高级的文件、文件夹、压缩包处理模块
## 常用方法
### 拷贝内容
```python
import shutil
shutil.copyfileobj(open('a.txt','r'),open('a.txt.new','w'))
```
### 拷贝文件
```python
import shutil
shutil.copyfile('file.txt','file1.txt') # 目标文件无需存在
```
### 拷贝状态信息
```python
import shutil
shutil.copystat('file.txt','file1.txt') # 目标文件必须存在
```
### 移动文件
```python
import shutil
# 移动文件或目录
shutil.move(src_path, dst_path)
```
### 删除文件和目录
```python
import shutil
# 删除单个文件
shutil.rmtree(directory_path) # 删除整个目录树
shutil.remove(file_path) # 删除单个文件
```
### 创建目录
```python
import shutil
# 创建单个目录
shutil.mkdir(directory_path)
# 创建嵌套目录
shutil.makedirs(directory_path)
```
### 压缩和解压缩文件
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的
```python
import zipfile
# 压缩
z = zipfile.ZipFile('ab.zip', 'w')
z.write('a.txt')
z.write('b.txt')
z.close()
# 解压
z = zipfile.ZipFile('ab.zip', 'r')
z.extractall(path=r'C:\Users\Atopos\Desktop')
z.close()
```
```python
import tarfile
# 压缩文件
t = tarfile.open('/tmp/egon.tar','w')
t.add('/test1/a.py',arcname='a.bak')
t.add('/test1/b.py',arcname='b.bak')
t.close()
# 解压缩文件
t = tarfile.open('/tmp/egon.tar','r')
t.extractall('/egon')
t.close()
```