序列化: 简单理解就是将字典,列表这类的数据,打包保存在电脑硬盘中
pickle.dumps()
pickle.dump()
pickle.load()
json.dumps()
json.dump()
json.load()
用途:可以用来打包一整个class,但是有风险,有时会失败
pickle.dumps()
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来打包,否则可以考虑json
pickle.dump()
可以将数据直接打包转换成一个文件import pickle import os data = {"filemame": "f1.txt", "create_time": "today", "size": 111} with open("data.pkl", "wb") as f: pickle.dump(data, f) print(os.listdir()) ['new_file.txt', 'chinese.txt', 'test.file.py', 'data.pkl']
pickle.load()
,可以读取上述由pickle.dump()
打包生成的文件,并对其进行解析,还原成最初的数据with open("data.pkl", "rb") as f: data = pickle.load() print(data) {'filemame': 'f1.txt', 'create_time': 'today', 'size': 111}
除了打包常见的字典,列表,元组这类的数据,pickle甚至都可以打包Python的功能以及类
eg: 定义了一个File类,而且基于它生成了很多file实例,这些实例都是可以被pickle的
注意:在pickle解析时(也可以称作unpickle时),这个File
的class一定要有,不然反序列化会因为找不到File
类而失败
import pickle 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_mame): self.name = new_mame data = File("f2.txt", "now", 222) # 建立一个File的实例 # 存 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的实例, 我们可以按照正常的class方式使用它
但有些类型的对象是不能被序列化的,这些通常都是那些需要依赖外部系统状态的对象,比如打开的文件,网络连接,线程,进程,栈帧等。
如果在class中把上述的东西复制到了class的属性中,会在pickle的时候报错
import 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") data = File("f3,txt", "now", 222) with open("data.pkl", "wb") as f: pickle.dump(data, f) 报错: TypeError: cannot pickle '_io.TextIOWrapper' object
如果非要使用pickle保存,也是有办法可以解决的。
用户自定义类可以通过提供__getstate()__
和__setstate__()
方法来绕过pickle的这些限制。pickle.dump()
会调用__getstate__()
获取序列化的对象,__setstate__()__
在反序列化时被调用
import 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) f3,txt 222
json数据:Python中的字典、列表都可以是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()
,和pickle.dump()
非常像的方式import json 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
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) # 存,会报错 with open("data.json", "w") as f: json.dump(data, f)
对比 | Pickle | Json |
---|---|---|
存储格式 | Python特定的Bytes格式 | 通过JSON text格式,可用于常用的网络通讯中 |
数据种类 | 类,功能,字典,列表,元组等 | 和Pickle一样,但不能存类、功能 |
保存后可读性 | 不能直接阅读 | 能直接阅读 |
跨语言性 | 只能用在pyhton | 可以跨多语言读写 |
处理时间 | 长(需编码数据) | 短(不需编码) |
安全性 | 不安全 | 相对安全 |
参考:莫烦Python