15. 序列化模块json和pickle、os模块
1. 序列化模块
1.1 序列化与反序列化
(1)序列化
将原本的python数据类型字典、列表、元组 转换成json格式字符串的过程就叫序列化
(2)反序列化
将json格式字符串转换成python数据类型字典、列表、元组的过程就叫反序列化
(3)为什么要序列化
计算机文件中没有字典这种数据类型,将字典中的数据转换成字符串形式的数据就称为序列化
1.2 json模块
json格式的数据在几种不同的语言中是一个通用的数据格式
(1)将python数据转换成json格式的字符串
import json
a = {'name': 'messi', 'age': 37, 'club': 'miami', 'address': 'usa'}
# 将python数据转换为json字符串
b = json.dumps(a)
print(b, type(b)) # {"name": "messi", "age": 37, "club": "miami", "address": "usa"} <class 'str'>
# 将json字符串转换为python数据
c = json.loads(b)
print(c, type(c)) # {'name': 'messi', 'age': 37, 'club': 'miami', 'address': 'usa'} <class 'dict'>
# 将json字符串进行二进制编码,符合json格式的二进制数据也能转换为python数据
d = b.encode()
print(d, type(d)) # b'{"name": "messi", "age": 37, "club": "miami", "address": "usa"}' <class 'bytes'>
e = json.loads(d)
print(e, type(e)) # {'name': 'messi', 'age': 37, 'club': 'miami', 'address': 'usa'} <class 'dict'>
(2)json模块处理文件
import json
a = {'name': 'messi', 'age': 37, 'club': 'miami', 'address': 'usa'}
# 将python数据写入到json文件中
# 字典格式的单引号变成了双引号
with open('new.json', 'w', encoding='utf-8') as f:
json.dump(a, f, ensure_ascii=False)
# {"name": "messi", "age": 37, "club": "miami", "address": "usa"}
# 将json文件的数据转换成python数据
# json格式字典双引号变成了单引号
with open('new.json', 'r', encoding='utf-8') as f2:
data = json.load(f2)
print(data, type(data)) # {'name': 'messi', 'age': 37, 'club': 'miami', 'address': 'usa'} <class 'dict'>
python中的列表存到json中还是列表,python中的元组存到json中也成了列表
(3)python数据与json数据互转
from json.encoder import JSONEncoder
from json.decoder import JSONDecodeError
'''
+-------------------+---------------+
| Python | JSON |
+===================+===============+
| dict | object |
+-------------------+---------------+
| list, tuple | array |
+-------------------+---------------+
| str | string |
+-------------------+---------------+
| int, float | number |
+-------------------+---------------+
| True | true |
+-------------------+---------------+
| False | false |
+-------------------+---------------+
| None | null |
+-------------------+---------------+
'''
# 将 Python中的 字典 转换为JSON格式的字典
# 将 Python中的 元组和列表 转换为 JSON格式的列表
# 将 Python中的 字符串 转换为 JSON格式的字符串
# 将 Python中的 布尔值 True / False 转换为 JSON格式的 true / false
# 将 Python中的 None 转换为 JSON格式的 null
# 将 Python中的 整数 转换为 JSON格式的数字
(4)json参数补充
# json模块默认的编码格式是ASCII码
# 写数据的时候再在open参数中指定utf-8是不生效的
import json
a = {'name': 'messi', 'club': '迈阿密', 'num': '001'}
with open('new.json', mode='w', encoding='utf-8') as f1:
json.dump(a, f1)
# {"name": "messi", "club": "\u8fc8\u963f\u5bc6", "num": "001"}
# 于是就要对dump参数进行调整
with open('new.json', mode='w', encoding='utf-8') as f2:
json.dump(a, f2, ensure_ascii=False)
# ensure_ascii=True : 是否启用默认的编码格式 如果是 True 则默认使用 ASCII 码格式,如果是 False 则使用 Unicode 格式
# {"name": "messi", "club": "迈阿密", "num": "001"}
1.3 pickle模块
pickle模块和json模块都是用来序列化和反序列化python数据的
json处理不了python中的函数和类,于是有了pickle
pickle格式是一种用于序列化和反序列化Python对象的二进制格式。
(1)将python数据转换成二进制数据
import pickle
def add(x, y):
return x + y
a = pickle.dumps(obj=add)
print(a, type(a))
# b'\x80\x04\x95\x14\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main__\x94\x8c\x03add\x94\x93\x94.' <class 'bytes'>
b = pickle.loads(a)
print(b, type(b))
# 得到一个内存地址,为函数类型
# <function add at 0x000001F7ABBE3370> <class 'function'>
(2)将python数据转换成二进制数据并写入文件
import pickle
def add(x, y):
print(x + y)
# 生成的aaa文件不可打开,但是可调用
with open('aaa', 'wb') as f1: # 由于pickle是将python数据序列化为二进制,因此写模式为wb
pickle.dump(add, f1)
with open('aaa', 'rb') as f2:
new_add = pickle.load(f2)
print(new_add, type(new_add))
# <function add at 0x000001D099E83370> <class 'function'>
# pickle先将函数名转换成二进制写到文件中,后将文件中二进制数据转换为函数名
new_add(11, 22) # 33 转回的函数仍旧可调用
2. os模块
os模块用于与操作系统交互
2.1 os.path.*
import os
import datetime
# (1)os.path.abspath 获取当前文件的绝对路径
print(os.path.abspath(__file__)) # D:\project\pythonProject\day14_部分模块\test.py
# (2)os.path.dirname 获取当前文件所在文件夹的绝对路径
print(os.path.dirname(__file__)) # D:\project\pythonProject\day14_部分模块
# (3)os.path.exists 判断文件夹是否存在
a = 'D:\project\pythonProject\day14_部分模块'
print(os.path.exists(a)) # True
b = 'D:\project\pythonProject\day14_usual'
print(os.path.exists(b)) # False
# (4)os.path.join 拼接文件路径
c = os.path.join('D:\project\pythonProject\day14_部分模块', 'giao')
print(c) # D:\project\pythonProject\day14_部分模块\giao
print(os.path.exists(c)) # False
# (5)os.path.split 将路径分隔为最后一级和上一级并以二元元组返回
d = os.path.split('D:\project\pythonProject\day14_部分模块\\test.py') # 加一个反斜杠取消转义
print(d) # ('D:\\project\\pythonProject\\day14_部分模块', 'test.py')
e = os.path.split('D:\project\pythonProject\day14_部分模块')
print(e) # ('D:\\project\\pythonProject', 'day14_部分模块')
# (6)os.path.basename 获取最后一级文件名/目录名
f = os.path.basename('D:\project\pythonProject\day14_部分模块\\test.py')
print(f) # test.py
g = os.path.basename('D:\project\pythonProject\day14_部分模块')
print(g) # day14_部分模块
# (7)os.path.isfile 判断当前路径是否为文件
h = os.path.isfile('D:\project\pythonProject\day14_部分模块\\test.py')
print(h) # True
i = os.path.isfile('D:\project\pythonProject\day14_部分模块')
print(i) # False
# (8)os.path.isabs 判断是否为绝对路径
j = '.\\test.py'
print(os.path.isabs(j)) # False
print(os.path.isabs('D:\project\pythonProject\day14_部分模块\\test.py')) # True
# (9)os.path.isdir 判断是否为目录
print(os.path.isdir('D:\project\pythonProject\day14_部分模块\\test.py'))
# False
print(os.path.isdir('D:\project\pythonProject\day14_部分模块'))
# True
# (10)os.path.getatime 获取当前文件或目录的最后访问时间atime---access time
k = os.path.getatime('D:\project\pythonProject\day14_部分模块\\test.py')
print(k) # 1722512134.9196131
print(datetime.datetime.fromtimestamp(k)) # 2024-08-01 19:35:34.919613
# (11)os.path.getctime 获取当前文件或目录的创建时间ctime---create time
l = os.path.getctime('D:\project')
print(l) # 1721123236.0086133
print(datetime.datetime.fromtimestamp(l)) # 2024-07-16 17:47:16.008613
# (12)os.path.getmtime 获取当前文件或目录的修改时间mtime---modifytime
m = os.path.getmtime('D:\project\pythonProject')
print(m) # 1722504598.081404
print(datetime.datetime.fromtimestamp(m)) # 2024-08-01 17:29:58.081404
# (13)os.path.getsize 获取当前文件或目录的大小,单位为byte
print(os.path.getsize('D:\project\pythonProject\day14_部分模块\\test.py')) # 2975
# (14)os.path.sep 获取系统对应的路径分隔符 MacOs、Linux: / Windows: \
print(os.path.sep) # \
2.2 路径操作 os.*
(1)创建单级文件夹
import os
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) # 获取当前文件所在的目录
print(CURRENT_DIR) # D:\project\pythonProject\day14_部分模块
# (1)创建单级文件夹
new_dir = os.path.join(CURRENT_DIR, 'giao') # 只是拼接了并没有创建
print(new_dir) # D:\project\pythonProject\day14_部分模块\giao
print(os.path.exists(new_dir)) # False
os.mkdir(new_dir) # 真正生成了新的文件夹
print(os.path.exists(new_dir)) # True
(2)创建多级文件夹
import os CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) # 获取当前文件所在的目录 new_dir = os.path.join(CURRENT_DIR, 'giu', 'giao') # 在当前文件所在目录再往下拼接两级目录 print(new_dir) # D:\project\pythonProject\day14_部分模块\giu\giao print(os.path.exists(new_dir)) # False os.makedirs(new_dir) # 创建拼接好的两个目录 print(os.path.exists(new_dir)) # True
import os
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) # 获取当前文件所在的目录
new_dir = os.path.join(CURRENT_DIR, 'giu', 'giao') # 在当前文件所在目录再往下拼接两级目录
print(new_dir) # D:\project\pythonProject\day14_部分模块\giu\giao
print(os.path.exists(new_dir)) # False
os.makedirs(new_dir, exist_ok=True)
# exist_ok=True 自动判断当前文件路径是否存在,如果不存在则主动创建,如果存在则忽略
(3)删除单级文件夹
import os
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) # 获取当前文件所在的目录
new_dir = os.path.join(CURRENT_DIR, 'giu', 'giao') # 在当前文件所在目录再往下拼接两级目录
os.makedirs(new_dir, exist_ok=True)
print(new_dir) # D:\project\pythonProject\day14_部分模块\giu\giao
# os.rmdir 只能删除单级文件夹且单级文件夹为空
os.rmdir(new_dir) # D:\project\pythonProject\day14_部分模块\giu
print(os.path.exists(new_dir)) # False
os.rmdir('D:\project\pythonProject\day13_模块与包') # OSError: [WinError 145] 目录不是空的。
(4)删除多级文件夹
import os
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) # 获取当前文件所在的目录
new_dir = os.path.join(CURRENT_DIR, 'giu', 'giao') # 在当前文件所在目录再往下拼接两级目录
os.makedirs(new_dir, exist_ok=True)
print(new_dir) # D:\project\pythonProject\day14_部分模块\giu\giao
# os.removedirs 若目录为空,则删除,并递归到上一级目录,若也为空,则删除,以此类推
os.removedirs(new_dir) # D:\project\pythonProject\day14_部分模块
(5)列出当前目录下的所有文件名
import os
# listdir的用法
print(os.path.dirname(os.path.abspath(__file__))) # 获取当前文件所在目录
print(os.listdir(os.path.dirname(os.path.abspath(__file__)))) # ['new.json', 'task.py', 'test.py']
(6)重命名当前文件或目录
rename的用法
重命名目录
import os
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) # 获取当前文件所在的目录
new_name = os.path.join(CURRENT_DIR, 'giao') # 在当前文件所在目录再拼接一个目录
os.makedirs(new_name, exist_ok=True)
print(new_name) # D:\project\pythonProject\day14_部分模块\giao
new_name2 = os.path.join(CURRENT_DIR, 'giu') # 拼接一个新的名称
print(new_name2) # D:\project\pythonProject\day14_部分模块\giu
os.rename(new_name, new_name2) # 用最新的替换原来的
重命名文件名
import os
CURRENT_FILE = os.path.abspath(__file__) # 获取当前文件绝对路径
print(CURRENT_FILE) # D:\project\pythonProject\day14_部分模块\task.py
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) # 获取当前文件所在的目录
new_filename = os.path.join(CURRENT_DIR, 'workon.py') # 拼接一个新的文件名称
print(new_filename) # D:\project\pythonProject\day14_部分模块\workon.py
os.rename(CURRENT_FILE, new_filename) # 用新的名称替换原来的
(7)删除指定文件
os.remove的用法
(8)列出当前文件的元信息
import os
print(os.stat(os.path.abspath(__file__)))
# 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)是最新的元数据更改的时间
(9)获取当前所在的工作目录
import os print(os.getcwd()) # D:\project\pythonProject\day14_部分模块
(10)切换工作目录
import os
print(os.getcwd()) # 当前路径 D:\project\pythonProject\day14_部分模块
os.chdir('D:\project\pythonProject\day13_模块与包') # 切换路径
print(os.getcwd()) # D:\project\pythonProject\day13_模块与包
(11)执行shell命令
操作系统不同则命令名称也不同
(12)执行命令获取结果
import os
res = os.system('dir')
print(res)
2.3 os模块操作补充
# (1)获取操作系统的路径分隔符
import os
print(os.sep) # \
print(os.path.sep) # \
# (2)获取操作系统的行终止符
import os
print(os.linesep) # \r\n
# (4)查看操作系统的标识 import os print(os.name) # nt