我是Python的新手,正在和Pickle一起玩,不了解它是如何工作的
我定义一个defaultdict,将其写入pickle。然后,在另一个脚本中,我阅读了该脚本,即使不导入集合,它的行为仍类似于defaultdict
脚本1:
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 )
脚本2:
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,但是 pickle 的x仍然像一个一样。我很困惑 :)
这在Python中如何运作?感谢您提供任何信息:)
最佳答案
首先,如果您查看pickle docs,特别是:
因此,这告诉我们, pickle 将导入定义您要去除的对象的模块。
我们可以通过一个小示例来说明这一点,请考虑以下文件夹结构:
parent/
|-- a.py
|-- sub/
sub
是一个空的子文件夹a.py
包含一个示例类# a.py
class ExampleClass:
def __init__(self):
self.var = 'This is a string'
现在启动
python
目录中的parent
控制台: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 。移至
sub
目录,并尝试加载 pickle 的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
加载类定义(它在另一个目录中)。在您的情况下,由于此模块位于collections.defaultdict
上,因此python可以加载PYTHONPATH
类。但是,要继续使用pickle导入的模块,您仍然需要自己导入它们。例如,您想在defaultdict
中创建另一个script2.py
。要查找有关模块的更多信息,请查看here,特别是6.1.2 The Module Search Path。