python - Python:Pickle 如何与 defaultdict 一起工作
问题描述
我是 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 但腌制的 x 仍然像一个。我很困惑 :)
这在 Python 中是如何工作的?感谢您提供任何信息:)
解决方案
首先,如果您查看pickle docs,特别是:
pickle 可以透明地保存和恢复类实例,但是类定义必须是可导入的,并且与存储对象时位于同一模块中
所以这告诉我们的是,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)
退出外壳。移动到sub
目录并尝试加载腌制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 导入的模块,您仍然需要自己导入它们;例如,您想defaultdict
在script2.py
.
要了解有关模块的更多信息,请查看此处,特别是6.1.2 模块搜索路径。
推荐阅读
- string - Kotlin String.format() 使我的文本居中
- python - Python ThreadpoolExecutor 属性错误
- django - django rest框架中用于社交登录的Firebase身份验证
- javascript - 在 react-native 上使用 onSnapshot() 时显示 Firestore 时间戳会出错
- node.js - 如何使用nodejs和mongodb正确处理promise
- gitlab - GitLab CI 模板 - 模板本地的参考文件/脚本
- javascript - 为什么我需要在此函数中使用 return 关键字才能使 promise 正常工作?
- telegram - 电报太多请求
- c# - 用于分页的 neo4j 结果的内存缓存
- sql - 在两个表之间查找丢失的数据 mysql workench