python pickle 上的命名空间

Posted

技术标签:

【中文标题】python pickle 上的命名空间【英文标题】:namespace on python pickle 【发布时间】:2011-12-17 05:25:03 【问题描述】:

当我将 pickle 与 unittest 一起使用时出现错误。

我写了3个程序文件:

    要腌制的类, 对于使用 #1 中的类的类, unittest 用于测试 #2 中的类。

实际代码分别如下。

#1。 ClassToPickle.py

import pickle
class ClassToPickle(object):
    def __init__(self, x):
        self.x = x
if __name__=="__main__":
    p = ClassToPickle(10)
    pickle.dump(p, open('10.pickle', 'w'))

#2。 SomeClass.py

from ClassToPickle import ClassToPickle
import pickle

class SomeClass(object):
    def __init__(self):
        self.pickle = pickle.load(open("10.pickle", 'r'))
        self.x = self.pickle.x
        print self.x

if __name__ == "__main__":
    SomeClass()

#3。 SomeClassTest.py

import unittest
from SomeClass import SomeClass
from ClassToPickle import ClassToPickle # REQUIRED_LINE

class SomeClassTest(unittest.TestCase):
    def testA(self):
        sc = SomeClass()
        self.assertEqual(sc.x, 10)

def main():
    unittest.main()

if __name__ == "__main__":
    main()

我首先运行 #1 程序来制作泡菜文件。 然后,当我单独运行程序文件 #2 时(即输入“python SomeClass.py”),它就可以工作了。 而且,当我单独运行程序 #3(即输入“python SomeClassTest.py”)时,它也可以工作。

但是,当我在 eclipse+pydev 中将程序 #3 作为“单元测试”运行时,它会返回以下错误消息。

================================================ ======================== 错误:testA (SomeClassTest.SomeClassTest) -------------------------------------------------- -------------------- Traceback(最近一次调用最后一次):$ 文件 “/home/tmp/pickle_problem/SomeClassTest.py”,第 9 行,在 测试A sc = SomeClass()$ 文件“/home/tmp/pickle_problem/SomeClass.py”,第 8 行,在 初始化 self.pickle = pickle.load(open("10.pickle", 'r'))$ 文件“/usr/lib/python2.7/pickle.py”,第 1378 行,加载中 返回 Unpickler(file).load()$ 文件“/usr/lib/python2.7/pickle.py”,第 858 行,加载中 dispatchkey 文件“/usr/lib/python2.7/pickle.py”,第 1090 行,在 load_global klass = self.find_class(module, name)$ 文件“/usr/lib/python2.7/pickle.py”,第 1126 行,在 find_class klass = getattr(mod, name)$ AttributeError: 'module' 对象没有属性 'ClassToPickle' -------------------------------------------------- -------------------- 在 0.002 秒内运行 1 次测试 FAILED (errors=1)

而且,当我注释掉导入 ClassToPickle 类的行(程序 #3 中的第 3 行并注释为“REQUIRED_LINE”)时,它不起作用并返回如下所述的错误消息。

电子 ==================================================== ===================== 错误:testA (ma​​in.SomeClassTest) -------------------------------------------------- -------------------- 回溯(最近一次通话最后一次): 文件“SomeClassTest.py”,第 9 行,在 testA sc = SomeClass()init 中的文件“/home/tmp/pickle_problem/SomeClass.py”,第 8 行 self.pickle = pickle.load(open("10.pickle", 'r')) 文件“/usr/lib/python2.7/pickle.py”,第 1378 行,加载中 返回 Unpickler(file).load() 文件“/usr/lib/python2.7/pickle.py”,第 858 行,加载中 调度键 文件“/usr/lib/python2.7/pickle.py”,第 1090 行,在 load_global klass = self.find_class(模块,名称) 文件“/usr/lib/python2.7/pickle.py”,第 1126 行,在 find_class klass = getattr(mod, name) AttributeError:“模块”对象没有属性“ClassToPickle” -------------------------------------------------- -------------------- 在 0.001 秒内运行 1 次测试 失败(错误=1)

我猜这个问题是关于 python 中的命名空间,但我不知道到底发生了什么以及我能做些什么来解决它。

如何正确“作为单元测试运行(在 eclipse+pydev 中)”#3 程序, 并在没有导入 ClassToPickle 的行的命令行中运行 #3 程序? 请帮帮我。

【问题讨论】:

是否有另一个 ClassToPickle.py 文件可以找到,而不是您在此处显示的文件? @ThomasK 感谢您的评论,但答案是否定的。目录中只有三个此处显示的 .py 文件,而且我从未创建名为 ClassToPickle.py 的文件。 【参考方案1】:

那是因为__main__.ClassToPickle != ClassToPickle.ClassToPickle,这样想:

当您在ClassToPickle.py 脚本中腌制 ClassToPickle 的类实例时,腌制模块将腌制对该类的所有引用,这意味着它将腌制定义该类的模块名称,并且因为您执行了脚本@ 987654323@ 这意味着模块将被设置为__main__ 这意味着pickle 模块将腌制__main__.ClassToPickle

当您尝试加载腌制实例时它失败了,因为它没有找到实例的类 __main__.ClassToPickle 而不是您使用 from ClassToPickle import ClassToPickle 导入的类,因为最新的是 ClassToPickle.ClassToPickle

解决方法是创建另一个脚本来处理转储,而不是在 ClassToPickle.py 中进行处理,例如

import pickle

from ClassToPickle import ClassToPickle

if __name__=="__main__":
    p = ClassToPickle(10)
    pickle.dump(p, open('10.pickle', 'w'))

【讨论】:

感谢您的解释!这一切对我来说都很有意义,你的脚本在控制台和 Eclipse 中都可以工作:) @fbessho:很高兴有帮助 :)

以上是关于python pickle 上的命名空间的主要内容,如果未能解决你的问题,请参考以下文章

Python3 中的 Python 命名空间包

python命名空间的本质

命名空间

python命名空间和作用域

python进阶之命名空间与作用域

Python之命名空间闭包装饰器