gpt4 book ai didi

python - 如何使用 iPython 进行解压?

转载 作者:太空狗 更新时间:2023-10-29 21:27:34 25 4
gpt4 key购买 nike

我正在尝试在 iPython 中加载 pickle 对象。

我得到的错误是:

AttributeError: 'FakeModule' object has no attribute 'World'



有谁知道如何让它工作,或者至少是在 iPython 中加载对象以便交互式浏览它们的解决方法?

谢谢

编辑添加:

我有一个名为 world.py 的脚本,它基本上可以:
import pickle
class World:
""
if __name__ == '__main__':
w = World()
pickle.dump(w, open("file", "wb"))

比在 REPL 中我做的:
import pickle  
from world import World
w = pickle.load(open("file", "rb"))

它适用于 vanilla python REPL,但不适用于 iPython。

我正在使用 Enthought Python Distribution 中的 Python 2.6.5 和 iPython 0.10,但我也遇到了以前版本的问题。

最佳答案

看起来您在 pickle 数据和尝试解开数据之间修改了 FakeModule:具体来说,您已经从该模块中删除了一些名为 World 的顶级对象(可能是一个类,也可能是一个函数) .

Pickling“按名称”序列化类和函数,因此它们需要是其模块顶层的名称,并且不得修改该模块(至少不会以这种方式严重影响这些名称——绝对不是通过 删除 这些名称来自模块!)介于 pickle 时间和解酸时间之间。

一旦您准确地确定了您所做的阻碍解压的更改,如果由于其他原因您不能只是恢复更改,它通常可能会被黑客入侵。例如,如果您刚刚将 WorldFakeModule 移动到 CoolModule ,请执行以下操作:

import FakeModule
import CoolModule
FakeModule.World = CoolModule.World

就在解压之前(记得用新的结构再次 pickle ,这样每次解压时就不必重复这些技巧;-)。

编辑 :OP 对 Q 的编辑使他的错误更容易理解。由于他现在正在测试 __name__ 是否等于 '__main__' ,因此很明显 pickle 在写入时将保存 __main__.World 类的对象。由于他使用的是 ASCII pickle (顺便说一下, 对于性能和磁盘空间来说非常糟糕的选择 ),检查一下很简单:
$ cat file
(i__main__
World
p0
(dp1

正在查找的模块是(清楚而明显地) __main__ 。现在,甚至不用打扰 ipython,而是使用一个简单的 Python 交互式解释器:
$ 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'
>>>

该错误很容易重现,其原因也很明显:执行类名查找的模块(即 __main__ )确实没有名为“World”的属性。模块 world 确实有一个,但是 OP 并没有像我在答案的前一部分中解释的那样“连接点”,在 pickle 文件需要它的模块中放置了一个具有正确名称的引用。那是:
>>> World = world.World
>>> pickle.load(open("file", "rb"))
<world.World instance at 0xf5300>
>>>

现在这当然完美无缺(正如我之前所说的)。也许 OP 没有看到这个问题,因为他使用了我讨厌的导入形式 from world import World(从模块内直接导入函数或类,而不是模块本身)。

解决 ipython 中问题的技巧在底层 Python 架构方面完全相同——只需要多几行代码,因为 ipython 提供所有额外服务, 不是 使模块 __main__ 直接可用于直接记录在交互式命令行上发生的事情,而是插入一个(称为 FakeModule,正如 OP 从错误 msg 中发现的那样;-)并用它做黑魔法以“酷”&c。尽管如此,无论何时您想直接访问具有给定名称的模块,这在 Python 中都非常简单,当然:
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]:

要记住的第一课:避免使用黑魔法,至少除非并且直到您成为一名巫师学徒,能够发现并解决其偶尔失控的情况(否则,那些提着水桶的扫帚最终可能会淹没世界当你小睡时;-)。

或者,另一种阅读:要正确使用某个抽象层(例如 ipython 放在 Python 之上的“酷”抽象层),您需要对底层有深入的了解(这里是 Python 本身及其核心机制,例如 pickling 和 sys .模块)。

第二课:由于您编写它的方式,pickle 文件基本上已损坏,因为只有当模块 __main__ 具有名称为 Word 的类时才能加载它,当然,如果没有像以上。 pickle 文件应该将类记录为位于模块 world 中。如果您绝对认为 必须 if __name__ == '__main__': 中的 world.py 子句上生成文件,那么为此目的使用一些冗余:
import pickle
class World:
""
if __name__ == '__main__':
import world
w = world.World()
pickle.dump(w, open("file", "wb"))

这工作正常并且没有黑客攻击(至少如果您遵循 Python 最佳实践,即在模块顶层永远不会有任何实质性代码——只有导入、类、定义和琐碎的分配——其他一切都属于函数;如果你没有t 遵循这个最佳实践,然后编辑你的代码来这样做,它会让你在灵活性和性能方面更快乐)。

关于python - 如何使用 iPython 进行解压?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3431419/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com