今天早些时候,我在尝试腌制时遇到了麻烦命名元组 http://docs.python.org/2/library/collections.html#namedtuple-factory-function-for-tuples-with-named-fields实例。作为健全性检查,我尝试运行一些发布的代码在另一个答案中 https://stackoverflow.com/a/16377267/553404。在这里,稍微简化一下:
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")
to 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
参数需要与工厂名称匹配才能正常工作吗?