我试图在iPython中加载pickled对象。在
我得到的错误是:
AttributeError: 'FakeModule' object has no attribute 'World'
有没有人知道如何让它工作,或者至少有一个变通方法来加载iPython中的对象,以便以交互方式浏览它们?在
谢谢
编辑后添加:
我有一个剧本叫世界.py基本上是这样的:
import pickle
class World:
""
if __name__ == '__main__':
w = World()
pickle.dump(w, open("file", "wb"))
而不是在回复中:
^{pr2}$它在vanilla python REPL中工作,但在iPython中不起作用。在
我使用的python2.6.5和ipython0.10都来自于热情的Python发行版,但是我在以前的版本中也遇到了问题。在
看起来您已经修改了
FakeModule
在您对数据进行pickle的这段时间内:具体地说,您已经从该模块中删除了一些名为World
(可能是一个类,也许是一个函数)的顶级对象。在Pickling将类和函数“按名称”序列化,因此它们必须是模块顶层的名称,并且不能修改该模块(至少不能通过将这些名称从模块中删除而严重影响这些名称)在酸洗时间和不酸洗时间之间。在
一旦你确定了你做了什么样的改变阻碍了不停的工作,如果因为其他原因你不能恢复这些改变,它通常会被黑客攻击。例如,如果您刚刚将
World
从FakeModule
移动到CoolModule
,请执行以下操作:在取消拾取之前(记住再次使用新结构进行pickle,这样您就不必每次取消拾取时都重复这些技巧;-)。在
编辑:操作员对Q的编辑使他的错误更容易理解。因为他现在正在测试
^{pr2}$__name__
是否等于'__main__'
,这使得pickle在编写时将保存一个__main__.World
类的对象。因为他使用的是ASCII pickle(顺便说一下,对于性能和磁盘空间来说,这是一个非常不好的选择),所以检查一下:正在查找的模块是
__main__
。现在,不用费心ipython,只需使用一个简单的Python交互式解释器:这个错误很容易重现,其原因也是显而易见的:执行类名查找的模块(即,
__main__
)确实没有名为“World”的属性。模块world
确实有一个,但是OP没有像我在前面的回答中所解释的那样“连接点”,在pickle文件需要它的模块中放置一个具有正确名称的引用。即:当然,这一切都很完美(正如我之前所说)。也许OP没有看到这个问题,因为他使用的是import I detest,
from world import World
(直接从模块中导入函数或类,而不是从模块本身导入)。在ipython中解决这个问题的方法在底层Python架构方面是完全相同的,只需要多出几行代码,因为ipython要提供所有额外的服务,没有使模块
__main__
直接用于记录交互命令行上发生的事情,而是插入一个(称为FakeModule,正如OP从错误msg;-)中发现的那样,并对其执行魔术,以使其“酷”&c。不过,无论何时,只要您想直接访问具有给定名称的模块,在Python中这是非常微不足道的,当然:要记住的教训,第一:避免使用黑魔法,至少在你成为一个足够好的巫师学徒,能够发现并修复它偶尔失控的情况(否则,那些提着水桶的扫帚可能会在你午睡时淹没整个世界;-)。在
或者,另一种解读:要正确使用某个抽象层(比如ipython在Python之上设置的“酷”抽象层),您需要对底层(这里是Python本身及其核心机制,如pickling和系统模块). 在
第二课:pickle文件本质上是损坏的,这是由于您编写它的方式造成的,因为它只能在模块
__main__
有一个名为Word
的类时加载,当然,没有上面的一些技巧,它通常不会有。pickle文件应该将类记录为活在模块world
中。如果您绝对认为必须在world.py
中的if __name__ == '__main__':
子句上生成文件,那么请使用一些冗余来达到以下目的:这个很好用出窍门(至少,如果您遵循Python的最佳实践,即在模块顶层没有任何实质性的代码,只有导入、类、def和琐碎的赋值;如果您没有遵循这个最佳实践,那么就编辑您的代码,这样做,它将使您在灵活性和性能方面更加快乐。在
当用}模块的事实记录在
pickle.dump(w, open("file", "wb"))
在__main__
模块中picklew
时,w
来自{file
的第一行:当IPython尝试取消拾取
^{pr2}$file
时,它执行以下行:特别是,它尝试执行
__import__('__main__')
。如果你在REPL中尝试,你会得到这就是IPython在AttributeError中提到的
FakeModule
。在如果你往里看之前或之后说
fake.__dict__
你会发现它不包括World
,即使你在^{from test import World
。在如果你跑了
那么
pickle.load
将起作用:可能有更干净的方法,我不知道。任何你能想到的将
World
放在fake
命名空间中的方法都应该有效。在2008年,IPython的创造者费尔南多·佩雷斯(fernandoperez)就这个问题发表了看法。他可能已经用某种方法解决了这个问题,以避免我的下流。您可能想询问IPython用户邮件列表,或者,也许更简单一些,只是不要在
__main__
名称空间内进行pickle。在相关问题 更多 >
编程相关推荐