我是
Python的新手,正在玩Pickle并且不明白它是如何工作的
我定义了一个defaultdict,把它写入pickle.然后在另一个脚本中我读了它,即使没有导入集合,它仍然表现得像一个defaultdict
SCRIPT1:
import pickle
from collections import defaultdict
x = defaultdict(list)
x['a'].append(1)
print(x)
with open('pick','wb') as f:
pickle.dump( x, f )
SCRIPT2:
import pickle
with open('pick','rb') as f:
x = pickle.load( f )
x['b'].append(2)
print(x)
y = dict()
try:
y['b'].append(2)
print(y)
except KeyError:
print("Can't append to y")
运行:
$python3 pick2.py
defaultdict(<class 'list'>, {'a': [1], 'b': [2]})
Can't append to y
因此,第二个脚本不会导入defaultdict但是pickled x仍然就像一个.我糊涂了 :)
这在Python中如何工作?谢谢你的任何信息:)
最佳答案 首先,如果你看一下
pickle docs,具体来说:
pickle can save and restore class instances transparently, however the class definition must be importable and live in the same module as when the object was stored
所以这告诉我们的是,pickle将导入定义你正在解开的对象的模块.
我们可以用一个小例子来展示这个,考虑以下文件夹结构:
parent/
|-- a.py
|-- sub/
sub是一个空的子文件夹
a.py包含一个示例类
# a.py
class ExampleClass:
def __init__(self):
self.var = 'This is a string'
现在启动父目录中的python控制台:
alex@toaster:parent$python3
>>> import pickle
>>> from a import ExampleClass
>>> x = ExampleClass()
>>> x.var
'This is a string'
>>> with open('eg.p', 'wb') as f:
... pickle.dump(x, f)
退出shell.移动到子目录并尝试加载pickled ExampleClass对象.
alex@toaster:sub$python3
>>> import pickle
>>> with open('../eg.p', 'rb') as f:
... x = pickle.load(f)
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ModuleNotFoundError: No module named 'a'
我们得到一个ModuleNotFoundError,因为pickle无法从模块a(它在不同的目录中)加载类定义.在您的情况下,python可以加载collections.defaultdict类,因为此模块位于PYTHONPATH上.但是,要继续使用pickle导入的模块,您仍然需要自己导入它们;例如,您想在script2.py中创建另一个defaultdict.
要了解有关模块的更多信息,请查看here,特别是6.1.2 The Module Search Path.