如何正确地腌制 namedtuple 实例

新手上路,请多包涵

我正在学习如何使用泡菜。我创建了一个 namedtuple 对象,将其附加到列表中,并尝试对该列表进行 pickle。但是,我收到以下错误:

 pickle.PicklingError: Can't pickle <class '__main__.P'>: it's not found as __main__.P

我发现如果我运行代码而不将其包装在函数中,它会完美运行。当包裹在函数中时,是否需要额外的步骤来腌制对象?

这是我的代码:

 from collections import namedtuple
import pickle

def pickle_test():
    P = namedtuple("P", "one two three four")
    my_list = []
    abe = P("abraham", "lincoln", "vampire", "hunter")
    my_list.append(abe)
    with open('abe.pickle', 'wb') as f:
        pickle.dump(abe, f)

pickle_test()

原文由 Dirty Penguin 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 629
2 个回答

在函数 外部 创建命名元组:

 from collections import namedtuple
import pickle

P = namedtuple("P", "one two three four")

def pickle_test():
    my_list = []
    abe = P("abraham", "lincoln", "vampire", "hunter")
    my_list.append(abe)
    with open('abe.pickle', 'wb') as f:
        pickle.dump(abe, f)

pickle_test()

现在 pickle 可以找到了;它现在是一个全球模块。 unpickling 时,所有 pickle 模块所要做的就是再次定位 __main__.P 。在您的版本中, Ppickle_test() 函数的 _本地_,并且不可自省或不可导入。

请注意, pickle 仅存储模块和类名,取自类的 __name__ 属性。确保 namedtuple() 调用的第一个参数与您分配给的全局变量相匹配; P.__name__ 必须是 "P"

重要的是要记住 namedtuple() 是一个类工厂;你给它参数,它返回一个类对象供你创建实例。 pickle 仅存储实例中包含的 _数据_,加上对原始类的字符串引用以再次重构实例。

原文由 Martijn Pieters 发布,翻译遵循 CC BY-SA 4.0 许可协议

我在另一个线程中找到 了这个答案。这就是命名元组的命名。这对我有用:

 group_t =            namedtuple('group_t', 'field1, field2')  # this will work
mismatched_group_t = namedtuple('group_t', 'field1, field2')  # this will throw the error

原文由 Ruvalcaba 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题