文件——存储原生的python对象:pickle | 第二部分 类型与操作 —— 第 9 章: 元组,文件和其他 |《学习 python:强大的面向对象编程(第 5 版)》| python 技术论坛-江南app体育官方入口
如前面代码中展示的,使用 eval
将字符串转换为对象,是一个强大的工具。事实上,有时它太强大了。eval
将很开心地运行任何python表达式——即使一个可能删除电脑上所有文件的表达式,假如有必要的权限!如果真的想存储原生的python对象,但又不能信任文件中的数据源,python的标准库 pickle
模块就很理想。
pickle
模块是一个更高级的工具,允许直接将几乎任何python对象存储在文件中,而对我们没有与字符串进行来回转换的要求。它就像一个超级通用的数据格式化和解析实用程序。比如,要存储字典在文件中,直接对它序列化:
>>> d = {'a': 1, 'b': 2}
>>> f = open('datafile.pkl', 'wb')
>>> import pickle
>>> pickle.dump(d, f) # pickle any object to file
>>> f.close()
然后,随后要取回字典,简单地再次使用 pickle
来创建它:
>>> f = open('datafile.pkl', 'rb')
>>> e = pickle.load(f) # load any object from file
>>> e
{'a': 1, 'b': 2}
我们取回了一个等价的字典对象,不需要手动分割或转换。pickle
模块执行了所谓的对象序列号——将对象与字节字符串相互转换——但对我们来说只需要很少的工作。事实上,pickle
在内部将字典转换为字符串形式,虽然没有什么好看的(而且如果在其它的数据协议模式下序列化,可能会有所不同):
>>> open('datafile.pkl', 'rb').read() # format is prone to change!
b'\x80\x03}q\x00(x\x01\x00\x00\x00bq\x01k\x02x\x01\x00\x00\x00aq\x02k\
x01u.'
因为 pickle
可以从这个格式重建对象,所以无需亲自处理它。要获取更多关于 pickle
模块的信息,请参见python标准库手册,或交互式地导入 pickle
然后把它传递给 help
。当探索时,还要看一下 shelve
模块。shelve
是一个工具,它使用pickle
把python对象存储在一个按键访问的文件系统中,这超过了这里的范围(虽然在第28章会看到一个 shelve
的实例,在第31和第37章还有其它 pickle
例子)。
注意
注意我以二进制模式打开用来存储序列化对象的文件;二进制模式在python 3.x 总是需要的,因为 pickler
(译注:help(pickle)
可以看到 pickler
是一个类,它有一个pickler
的方法) 创建并使用一个字节字符串对象,且这些对象意味着二进制模式的文件(文本模式文件在3.x中意味着 str
字符串)。在更早的python中,可以为 protocol 0
(默认值,它创建了ascii文本)使用文本模式文件),只要文本模式被一致地使用;更高的protocol
需要二进制模式文件。python 3.x的默认 protocol
是3(二进制),但即使对 protocol 0
它也创建 bytes
。参见第28、第31
、第37
章;python的库手册;或参考书获取更多关于序列化数据的知识和例子。
python 2.x also has a cpickle module, which is an optimized version of pickle that can be imported directly for speed. python 3.x 将此模块重命名为 _pickle
并在 pickle
中自动使用它——脚本简单地导入 pickle
然后让python优化它。