今天早些时候,我在尝试腌制一个命名元组实例时遇到了麻烦。作为健全性检查,我尝试运行一些发布在另一个答案中的代码。在这里,简化了一点:
from collections import namedtuple
import pickle
P = namedtuple("P", "one two three four")
def pickle_test():
abe = P("abraham", "lincoln", "vampire", "hunter")
f = open('abe.pickle', 'w')
pickle.dump(abe, f)
f.close()
pickle_test()
然后我更改了其中的两行以使用我的命名元组:
from collections import namedtuple
import pickle
P = namedtuple("my_typename", "A B C")
def pickle_test():
abe = P("ONE", "TWO", "THREE")
f = open('abe.pickle', 'w')
pickle.dump(abe, f)
f.close()
pickle_test()
然而,这给了我错误
File "/path/to/anaconda/lib/python2.7/pickle.py", line 748, in save_global
(obj, module, name))
pickle.PicklingError: Can't pickle <class '__main__.my_typename'>: it's not found as __main__.my_typename
即 Pickle 模块正在寻找my_typename
. 我将线路更改P = namedtuple("my_typename", "A B C")
为P = namedtuple("P", "A B C")
并且它有效。
我查看了来源,namedtuple.py
最后我们有一些看起来相关的东西,但我不完全理解发生了什么:
# For pickling to work, the __module__ variable needs to be set to the frame
# where the named tuple is created. Bypass this step in enviroments where
# sys._getframe is not defined (Jython for example) or sys._getframe is not
# defined for arguments greater than 0 (IronPython).
try:
result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
except (AttributeError, ValueError):
pass
return result
所以我的问题是到底发生了什么?为什么typename
参数需要与工厂名称匹配才能工作?