2022.11.17 本学习内容总结于莫烦python:6.pickle/json 序列化
https://mofanpy.com/tutorials/python-basic/interactive-python/pickle-json
参考:https://blog.csdn.net/weixin_43625577/article/details/86699789
6 pickle/json 序列化
6.1 序列化
序列化(Serialization):说简单也简单,就是把像字典,列表这类的数据,打包保存在电脑硬盘中。 如果粗略的理解对比,就有点像 zip 和 unzip 的过程。
在程序运行的过程中,所有的变量都是在内存中,比如,定义一个 dict:
a = {'name':'Bob','age':20,'score':90}
字典 a 可以随时修改变量,如果没有把修改后的 'name=Bill’存储到磁盘上,下次重新运行程序,变量又被初始化为 ‘Bob’。
我们把变量从内存中变成可存储或传输的过程称之为序列化,在 Python 中叫 pickling
。 序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即 unpickling
。
6.2 pickle
- pickle 序列化后的数据,可读性差,人一般无法识别;
- pickle 模块只能在 python 中使用,且只支持同版本,不能跨平台使用;
- Python 中所有的数据类型(列表,字典,集合,类等)都可以用 pickle 来序列化。
需导入 pickle 模块 — import pickle
6.2.1 打包字典、列表、元组
以字典为例:
- 打包
pickle.dumps(obj)
: 把 obj 对象序列化后以 bytes 对象返回,不写入文件
import pickle
data = {"filename": "f1.txt", "create_time": "today", "size": 111}
pickle.dumps(data)
b'\x80\x04\x958\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x08filename\x94\x8c\x06f1.txt\x94\x8c\x0bcreate_time\x94\x8c\x05today\x94\x8c\x04size\x94Kou.'
字典被 pickle 以后,已经面目全非,你不能直接读出来里面的信息,因为这些信息已经被编码了。
- 打包
pickle.dump(obj , file)
: 序列化对象,并将结果数据流写入到文件对象中
也就是有文件名,要用pickle.dump()
data = {"filename": "f1.txt", "create_time": "today", "size": 111}
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
import os
os.listdir()
['files', 'data.pkl']
with open() as f
:这个是打开文件,结束不用关闭文件。
with open(“data.pkl”, “wb”) as f:打开文件data.pkl,并进行二进制写操作
pickle.load(file)
: 反序列化对象,将文件中的数据解析为一个Python对象
with open("data.pkl", "rb") as f:
data = pickle.load(f)
print(data)
{'filename': 'f1.txt', 'create_time': 'today', 'size': 111}
6.2.2 打包 功能以及类
class File:
def __init__(self, name, create_time, size):
self.name = name
self.create_time = create_time
self.size = size
def change_name(self, new_name):
self.name = new_name
data = File("f2.txt", "now", 222)
# 存
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
# 读
with open("data.pkl", "rb") as f:
read_data = pickle.load(f)
print(read_data.name)
print(read_data.size)
`
f2.txt
222
读的过程就叫:unpickle
.你可以按正常的 class 方式使用这个 unpickle 的东西
6.2.3 无法序列化(打包)
有些类型的对象是不能被序列化的。这些通常是那些依赖外部系统状态的对象, 比如打开的文件,网络连接,线程,进程,栈帧等等
class File:
def __init__(self, name, create_time, size):
self.name = name
self.create_time = create_time
self.size = size
self.file = open(name, "w")
data = File("f3.txt", "now", 222)
# pickle 存,会报错
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
报错:self.file = open()
打开文件,依赖外部系统状态的对象赋值到了 class 的属性上,,这样的 class 在 pickle 的时候会报错的。
"""
Traceback (most recent call last):
File "<input>", line 11, in <module>
TypeError: cannot pickle '_io.TextIOWrapper' object
"""
- 解决方案:用户自定义类可以通过提供
__getstate__()
和__setstate__()
方法来绕过 pickle 的这些限制
class File:
def __init__(self, name, create_time, size):
self.name = name
self.create_time = create_time
self.size = size
self.file = open(name, "w")
def __getstate__(self):
# pickle 出去需要且能被 pickle 的信息
pickled = {"name": self.name, "create_time": self.create_time, "size": self.size}
return pickled
def __setstate__(self, pickled_dict):
# unpickle 加载回来,重组 class
self.__init__(
pickled_dict["name"], pickled_dict["create_time"], pickled_dict["size"])
data = File("f3.txt", "now", 222)
# 存
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
# 读
with open("data.pkl", "rb") as f:
read_data = pickle.load(f)
print(read_data.name)
print(read_data.size)
6.3 JSON
Python 中的 json 库,就是来处理 json 形式的数据的。
import json
data = {"filename": "f1.txt", "create_time": "today", "size": 111}
j = json.dumps(data)
print(j)
print(type(j))
{"filename": "f1.txt", "create_time": "today", "size": 111}
<class 'str'>
需要这样明文来存储数据的话,使用 json.dump()
data = {"filename": "f1.txt", "create_time": "today", "size": 111}
with open("data.json", "w") as f:
json.dump(data, f)
print("直接当纯文本读:")
with open("data.json", "r") as f:
print(f.read())
print("用 json 加载了读:")
with open("data.json", "r") as f:
new_data = json.load(f)
print("字典读取:", new_data["filename"])
直接当纯文本读:
{"filename": "f1.txt", "create_time": "today", "size": 111}
用 json 加载了读:
字典读取: f1.txt
json.load(f)
就把字典取出来了,直接用字典读取方式就可以读数了
6.4 Pickle 和 Json 的不同
json
相比 pickle
还是有它不及的点。我们上面已经看到,pickle
可以很轻松的打包 Python 的 class。
class File:
def __init__(self, name, create_time, size):
self.name = name
self.create_time = create_time
self.size = size
def change_name(self, new_name):
self.name = new_name
data = File("f4.txt", "now", 222)
# 存,会报错
json
不能序列化保存 class。你只能挑出来重要的信息,放到字典或列表里,然后再用json
打包字典。 下面就是一段 json 打包 class 会报错的代码。