使用pickle数据时,我遇到了io.open
和__builtin__.open
的不同行为。请考虑以下简单示例:
import pickle
payload = 'foo'
fn = 'test.pickle'
pickle.dump(payload, open(fn, 'w'))
a = pickle.load(open(fn, 'r'))
这可以按预期工作。但是在这里运行此代码:
import pickle
import io
payload = 'foo'
fn = 'test.pickle'
pickle.dump(payload, io.open(fn, 'w'))
a = pickle.load(io.open(fn, 'r'))
给出以下Traceback:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\WinPython-32bit-2.7.8.1\python-2.7.8\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 580, in runfile
execfile(filename, namespace)
File "D:/**.py", line 15, in <module>
pickle.dump(payload, io.open(fn, 'w'))
File "D:\WinPython-32bit-2.7.8.1\python-2.7.8\lib\pickle.py", line 1370, in dump
Pickler(file, protocol).dump(obj)
File "D:\WinPython-32bit-2.7.8.1\python-2.7.8\lib\pickle.py", line 224, in dump
self.save(obj)
File "D:\WinPython-32bit-2.7.8.1\python-2.7.8\lib\pickle.py", line 286, in save
f(self, obj) # Call unbound method with explicit self
File "D:\WinPython-32bit-2.7.8.1\python-2.7.8\lib\pickle.py", line 488, in save_string
self.write(STRING + repr(obj) + '\n')
TypeError: must be unicode, not str
由于我希望与未来兼容,我怎样才能避免这种不端行为呢?或者,我还有什么不对吗?
在使用string类型的键转储字典时,我偶然发现了这一点。
我的python版本是:
'2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)]'
答案 0 :(得分:2)
差别不大,因为io.open()
显式在使用文本模式时处理Unicode字符串。文档非常清楚:
注意:由于此模块主要是为Python 3.x设计的,因此您必须注意本文档中“bytes”的所有用法均指
str
类型(其中bytes
是别名),“text”的所有用法均指unicode
类型。此外,这两种类型在io API中不可互换。
和
Python区分以二进制和文本模式打开的文件,即使底层操作系统没有。以二进制模式打开的文件(包括模式参数中的
'b'
)将内容作为bytes
对象返回,而不进行任何解码。在文本模式下(默认情况下,或模式参数中包含't'
时),文件内容将作为unicode
字符串返回,字节已被首先解码使用依赖于平台的编码或使用指定的编码(如果给定)。
您需要以二进制模式打开文件。事实上它没有内置的open()
,实际上比智慧运气更多;如果您的泡菜包含\n
和/或\r
字节的数据,则泡菜加载可能会失败。 Python 2的默认pickle碰巧是一个文本协议,但输出应该仍被视为二进制。
在所有情况下,在编写pickle数据时,请使用二进制模式:
pickle.dump(payload, open(fn, 'wb'))
a = pickle.load(open(fn, 'rb'))
或
pickle.dump(payload, io.open(fn, 'wb'))
a = pickle.load(io.open(fn, 'rb'))