Pythonpickle教程展示了如何使用pickle模块在Python中进行数据序列化。
泡菜模块
pickle模块实现了用于序列化和反序列化Python对象结构的二进制协议。序列化是将内存中的对象转换为可以存储在磁盘上或通过网络发送的字节流的过程。反序列化是将字节流转换为Python对象的过程。
此过程也称为pickling/unpickling或marshalling/unmarshalling。
pickletools
模块包含用于分析pickle生成的数据流的工具。
Pythonpickle序列化
以下示例将数据序列化为二进制文件。
#!/usr/bin/python import pickle data = { 'a': [1, 4.0, 3, 4+6j], 'b': ("a red fox", b"and old falcon"), 'c': {None, True, False} } with open('data.bin', 'wb') as f: pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)
我们有一个不同数据类型的字典。数据被pickle成一个二进制文件。
with open('data.bin', 'wb') as f: pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)
dump
函数将对象的pickled表示写入文件对象。随着时间的推移,已经开发了几种协议。协议版本决定了序列化过程的能力。在我们的代码中,我们选择最高的协议版本。
$ hexdump -C data.bin 00000000 80 05 95 75 00 00 00 00 00 00 00 7d 94 28 8c 01 |...u.......}.(..| 00000010 61 94 5d 94 28 4b 01 47 40 10 00 00 00 00 00 00 |a.].(K.G@.......| 00000020 4b 03 8c 08 62 75 69 6c 74 69 6e 73 94 8c 07 63 |K...builtins...c| 00000030 6f 6d 70 6c 65 78 94 93 94 47 40 10 00 00 00 00 |omplex...G@.....| 00000040 00 00 47 40 18 00 00 00 00 00 00 86 94 52 94 65 |..G@.........R.e| 00000050 8c 01 62 94 8c 09 61 20 72 65 64 20 66 6f 78 94 |..b...a red fox.| 00000060 43 0e 61 6e 64 20 6f 6c 64 20 66 61 6c 63 6f 6e |C.and old falcon| 00000070 94 86 94 8c 01 63 94 8f 94 28 89 88 4e 90 75 2e |.....c...(..N.u.| 00000080
二进制文件不能用简单的文本编辑器读取;我们需要可以处理十六进制数据的工具。
Pythonpickle反序列化
在下一个示例中,我们从二进制文件中提取数据。
#!/usr/bin/python import pickle with open('data.bin', 'rb') as f: data = pickle.load(f) print(data)
load
函数从文件对象中读取对象的pickled表示,并返回重构的对象。
$ ./simple_read.py {'a': [1, 4.0, 3, (4+6j)], 'b': ('a red fox', b'and old falcon'), 'c': {False, True, None}}
我们已经成功地重新创建了字典对象。
Pythonpickle转储/加载
dumps
函数将对象的pickled表示作为字节对象返回,而不是将其写入文件。loads
函数返回对象的腌制表示数据的重构对象层次结构。数据必须是类似字节的对象。
#!/usr/bin/python import pickle data = [1, 2, 3, 4, 5] dumped = pickle.dumps(data) print(dumped) loaded = pickle.loads(dumped) print(loaded)
在示例中,我们使用dumps
和loads
序列化和反序列化Python列表。
$ ./dumps_loads.py b'\x80\x04\x95\x0f\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01K\x02K\x03K\x04K\x05e.' [1, 2, 3, 4, 5]
Python泡菜__getstate__/__setstate__
pickling和unpickling的过程可以通过__getstate__
和__setstate__
函数来影响。__getstate__
函数在pickling时调用,__setstate__
函数在unpickling时调用。
blue, rock, water, sky, cloud, forest, hawk, falcon
这是words.txt
文件
red, green, blue, pink, orange
这是colours.txt
文件
#!/usr/bin/python import pickle class MyData: def __init__(self, filename): self.name = filename self.fh = open(filename) def __getstate__(self): odict = self.__dict__.copy() print(odict) del odict['fh'] return odict def __setstate__(self, dict): fh = open(dict['name']) self.name = dict['name'] self.fh = fh obj = MyData('words.txt') res = pickle.loads(pickle.dumps(obj)) print(res.fh.read()) obj2 = MyData('colours.txt') res = pickle.loads(pickle.dumps(obj2)) print(res.fh.read())
在示例中,我们在__setstate__
和__getstate__
成员函数中存储和删除文件句柄。
$ ./state.py {'name': 'words.txt', 'fh': <_io.TextIOWrapper name='words.txt' mode='r' encoding='UTF-8'>} blue, rock, water, sky, cloud, forest, hawk, falcon {'name': 'colours.txt', 'fh': <_io.TextIOWrapper name='colours.txt' mode='r' encoding='UTF-8'>} red, green, blue, pink, orange
Pythonpickle是不安全的
pickle
模块是不安全的。该模块是一个虚拟机,它使用预定义的操作码来完成它的工作。通过使用特制的二进制字符串,攻击者可以启动系统命令来破坏数据或启动反向shell。
#!/usr/bin/python import pickle pickle.loads(b"cos\nsystem\n(S'ls -l'\ntR.")
此示例启动Linuxls
命令。
$ ./insec.py total 36 drwxr-xr-x 2 user2 user2 4096 Aug 13 16:16 Desktop drwxr-xr-x 2 user2 user2 4096 Aug 13 16:18 Documents drwxr-xr-x 2 user2 user2 4096 Aug 13 16:16 Downloads -rwxr-xr-x 1 user2 user2 79 Aug 29 11:08 insec.py drwxr-xr-x 2 user2 user2 4096 Aug 13 16:16 Music drwxr-xr-x 2 user2 user2 4096 Aug 13 16:16 Pictures drwxr-xr-x 2 user2 user2 4096 Aug 13 16:16 Public drwxr-xr-x 2 user2 user2 4096 Aug 13 16:16 Templates drwxr-xr-x 2 user2 user2 4096 Aug 13 16:16 Videos
这是一个示例输出。
在本教程中,我们使用了Pythonpickle模块。
列出所有Python教程。