当变量名称与类型名称不匹配时,namedtuple 酸洗失败
namedtuple pickling fails when variable name doesn't match typename
下面的 python 代码失败并出现错误 pickle.PicklingError: Can't pickle <class '__main__.SpecialName'>: it's not found as __main__.SpecialName
import pickle
from collections import namedtuple
different_SpecialName = namedtuple('SpecialName', 'foo bar')
def save():
foo = different_SpecialName(1, 2)
with open('foosave.pkl', 'w') as f:
pickle.dump(foo, f)
if __name__ == '__main__':
save()
这似乎是 pickle
模块的不良行为,因为它取决于 变量名称 的正确性。将 different_SpecialName
更改为 SpecialName
并重新 运行 代码使其成功完成。将代码更改为以下代码,其中 SpecialName
的变量被实例化为与 different_SpecialName
相同的值,也让代码 运行 成功
import pickle
from collections import namedtuple
different_SpecialName = namedtuple('SpecialName', 'foo bar')
## create new variable with 'correct' name
SpecialName = different_SpecialName
def save():
# foo = different_SpecialName(1, 2)
foo = SpecialName(1, 2)
with open('foosave.pkl', 'w') as f:
pickle.dump(foo, f)
if __name__ == '__main__':
save()
我的问题:这基本上是 pickle
(和 cPickle
)错误吗?似乎 pickle
不应该使用变量名称查找 class 定义(尽管我不确定它还能做什么)。或者,这是 namedtuple
API 的问题吗?我浏览了 namedtuple
documentation 并找不到任何明确告诉我将我的 namedtuple
变量命名为与我的 typename
参数相同的东西(namedtuple()
函数的第一个参数)
这不是错误。 pickle
requires那个
the class definition must be importable and live in the same module as when the object was stored.
从namedtuple
的__reduce__
方法来看,类型名是SpecialName
(毕竟你传的就是这个)。所以当 unpickling 时,它会尝试导入它在其中声明的模块并查找 SpecialName
。但是因为你没有保存为SpecialName
,所以找不到它。
如果不诉诸 namedtuple
s,您可以使用以下方法产生完全相同的问题:
class Foo:
pass
Bar = Foo
del Foo
并尝试腌制和解腌 Bar()
;在幕后,您实际上已经用 namedtuple
.
不匹配的名称做了同样的事情
下面的 python 代码失败并出现错误 pickle.PicklingError: Can't pickle <class '__main__.SpecialName'>: it's not found as __main__.SpecialName
import pickle
from collections import namedtuple
different_SpecialName = namedtuple('SpecialName', 'foo bar')
def save():
foo = different_SpecialName(1, 2)
with open('foosave.pkl', 'w') as f:
pickle.dump(foo, f)
if __name__ == '__main__':
save()
这似乎是 pickle
模块的不良行为,因为它取决于 变量名称 的正确性。将 different_SpecialName
更改为 SpecialName
并重新 运行 代码使其成功完成。将代码更改为以下代码,其中 SpecialName
的变量被实例化为与 different_SpecialName
相同的值,也让代码 运行 成功
import pickle
from collections import namedtuple
different_SpecialName = namedtuple('SpecialName', 'foo bar')
## create new variable with 'correct' name
SpecialName = different_SpecialName
def save():
# foo = different_SpecialName(1, 2)
foo = SpecialName(1, 2)
with open('foosave.pkl', 'w') as f:
pickle.dump(foo, f)
if __name__ == '__main__':
save()
我的问题:这基本上是 pickle
(和 cPickle
)错误吗?似乎 pickle
不应该使用变量名称查找 class 定义(尽管我不确定它还能做什么)。或者,这是 namedtuple
API 的问题吗?我浏览了 namedtuple
documentation 并找不到任何明确告诉我将我的 namedtuple
变量命名为与我的 typename
参数相同的东西(namedtuple()
函数的第一个参数)
这不是错误。 pickle
requires那个
the class definition must be importable and live in the same module as when the object was stored.
从namedtuple
的__reduce__
方法来看,类型名是SpecialName
(毕竟你传的就是这个)。所以当 unpickling 时,它会尝试导入它在其中声明的模块并查找 SpecialName
。但是因为你没有保存为SpecialName
,所以找不到它。
如果不诉诸 namedtuple
s,您可以使用以下方法产生完全相同的问题:
class Foo:
pass
Bar = Foo
del Foo
并尝试腌制和解腌 Bar()
;在幕后,您实际上已经用 namedtuple
.