<p>看起来您已经修改了<code>FakeModule</code>在您对数据进行pickle的这段时间内:具体地说,您已经从该模块中删除了一些名为<code>World</code>(可能是一个类,也许是一个函数)的顶级对象。在</p>
<p>Pickling将类和函数“按名称”序列化,因此它们必须是模块顶层的名称,并且不能修改该模块(至少不能通过将这些名称从模块中删除而严重影响这些名称)在酸洗时间和不酸洗时间之间。在</p>
<p>一旦你确定了你做了什么样的改变阻碍了不停的工作,如果因为其他原因你不能恢复这些改变,它通常会被黑客攻击。例如,如果您刚刚将<code>World</code>从<code>FakeModule</code>移动到<code>CoolModule</code>,请执行以下操作:</p>
<pre><code>import FakeModule
import CoolModule
FakeModule.World = CoolModule.World
</code></pre>
<p>在取消拾取之前(记住再次使用新结构进行pickle,这样您就不必每次取消拾取时都重复这些技巧;-)。在</p>
<p><strong>编辑</strong>:操作员对Q的编辑使他的错误更容易理解。因为他现在正在测试<code>__name__</code>是否等于<code>'__main__'</code>,这使得pickle在编写时将保存一个<code>__main__.World</code>类的对象。因为他使用的是ASCII pickle(顺便说一下,对于性能和磁盘空间来说,这是一个非常不好的选择),所以检查一下:</p>
^{pr2}$
<p>正在查找的模块是<code>__main__</code>。现在,不用费心ipython,只需使用一个简单的Python交互式解释器:</p>
<pre><code>$ py26
Python 2.6.5 (r265:79359, Mar 24 2010, 01:32:55)
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import world
>>> import pickle
>>> pickle.load(open("file", "rb"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py", line 1370, in load
return Unpickler(file).load()
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py", line 858, in load
dispatch[key](self)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py", line 1069, in load_inst
klass = self.find_class(module, name)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pickle.py", line 1126, in find_class
klass = getattr(mod, name)
AttributeError: 'module' object has no attribute 'World'
>>>
</code></pre>
<p>这个错误很容易重现,其原因也是显而易见的:执行类名查找的模块(即,<code>__main__</code>)确实没有名为“World”的属性。模块<code>world</code>确实有一个,但是OP没有像我在前面的回答中所解释的那样“连接点”,在pickle文件需要它的模块中放置一个具有正确名称的引用。即:</p>
<pre><code>>>> World = world.World
>>> pickle.load(open("file", "rb"))
<world.World instance at 0xf5300>
>>>
</code></pre>
<p>当然,这一切都很完美(正如我之前所说)。也许OP没有看到这个问题,因为他使用的是import I detest,<code>from world import World</code>(直接从模块中导入函数或类,而不是从模块本身导入)。在</p>
<p>ipython中解决这个问题的方法在底层Python架构方面是完全相同的,只需要多出几行代码,因为ipython要提供所有额外的服务,<strong>没有</strong>使模块<code>__main__</code>直接用于记录交互命令行上发生的事情,而是插入一个(称为FakeModule,正如OP从错误msg;-)中发现的那样,并对其执行魔术,以使其“酷”&c。不过,无论何时,只要您想直接访问具有给定名称的模块,在Python中这是非常微不足道的,当然:</p>
<pre><code>In [1]: import world
In [2]: import pickle
In [3]: import sys
In [4]: sys.modules['__main__'].World = world.World
In [5]: pickle.load(open("file", "rb"))
Out[5]: <world.World instance at 0x118fc10>
In [6]:
</code></pre>
<p>要记住的教训,第一:避免使用黑魔法,至少在你成为一个足够好的巫师学徒,能够发现并修复它偶尔失控的情况(否则,那些提着水桶的扫帚可能会在你午睡时淹没整个世界;-)。在</p>
<p>或者,另一种解读:要正确使用某个抽象层(比如ipython在Python之上设置的“酷”抽象层),您需要对底层(这里是Python本身及其核心机制,如pickling和系统模块). 在</p>
<p>第二课:pickle文件本质上是损坏的,这是由于您编写它的方式造成的,因为它只能在模块<code>__main__</code>有一个名为<code>Word</code>的类时加载,当然,没有上面的一些技巧,它通常不会有。pickle文件应该将类记录为活在模块<code>world</code>中。如果您绝对认为<strong>必须</strong>在<code>world.py</code>中的<code>if __name__ == '__main__':</code>子句上生成文件,那么请使用一些冗余来达到以下目的:</p>
<pre><code>import pickle
class World:
""
if __name__ == '__main__':
import world
w = world.World()
pickle.dump(w, open("file", "wb"))
</code></pre>
<p>这个很好用出窍门(至少,如果您遵循Python的最佳实践,即在模块顶层没有任何实质性的代码,只有导入、类、def和琐碎的赋值;如果您没有遵循这个最佳实践,那么就编辑您的代码,这样做,它将使您在灵活性和性能方面更加快乐。在</p>