gpt4 book ai didi

python - 使用 Python pickle 存储对象,并将其加载到不同的命名空间

转载 作者:太空狗 更新时间:2023-10-29 20:47:30 25 4
gpt4 key购买 nike

我想在两个 Python 程序(一个是我自己独立运行的代码,一个是 Pyramid View )和不同的命名空间之间传递对象状态。一些相关的问题是 herehere ,但我无法完全按照我的方案进行操作。

我自己的代码定义了一个结构有些复杂的全局类(即 __main__ 命名空间):

# An instance of this is a colorful mess of nested lists and sets and dicts.
class MyClass :
def __init__(self) :
data = set()
more = dict()
...

def do_sth(self) :
...

在某些时候我 pickle 这个类的一个实例:

c = MyClass()
# Fill c with data.

# Pickle and write the MyClass instance within the __main__ namespace.
with open("my_c.pik", "wb") as f :
pickle.dump(c, f, -1)

A hexdump -C my_c.pik 显示前几个字节包含 __main__.MyClass 从中我假设该类确实在全局命名空间中定义,这在某种程度上是阅读 pickle 的要求。现在我想从 Pyramid View 中加载这个 pickled MyClass 实例,我假设它是一个不同的命名空间:

# In Pyramid (different namespace) read the pickled MyClass instance.
with open("my_c.pik", "rb") as f :
c = pickle.load(f)

但这会导致以下错误:

File ".../views.py", line 60, in view_handler_bla
c = pickle.load(f)
AttributeError: 'module' object has no attribute 'MyClass'

在我看来, View 代码执行的任何命名空间中都缺少 MyClass 定义吗?我曾希望(假设)pickling 是一个有点不透明的过程,它允许我将一团数据读入我选择的任何地方。 (更多关于 Python 的类名和命名空间的信息是 here。)

我该如何正确处理这个问题? (理想情况下,无需导入内容...)我能以某种方式找到当前命名空间并注入(inject) MyClass(如 this 答案似乎暗示的那样)吗?

糟糕的解决方案

在我看来,如果我不定义和使用 MyClass 而是回退到普通的内置数据类型,这将不是问题。事实上,我可以将 MyClass 对象“序列化”为一系列调用,这些调用会挑选 MyClass 实例的各个元素:

# 'Manual' serialization of c works, because all elements are built-in types.
pickle.dump(c.data, f, -1)
pickle.dump(c.more, f, -1)
...

但这会破坏将数据包装到类中的目的。

注意

Pickling 只关心类的状态,类范围内定义的任何函数(例如上例中的 do_sth())。这意味着在没有正确类定义的情况下将 MyClass 实例加载到不同的命名空间中只会加载实例数据;调用缺少的函数,如 do_sth() 将导致 AttributeError .

最佳答案

使用 dill 而不是 pickle,因为 dill 默认情况下通过序列化类定义而不是通过引用来 pickles。

>>> import dill
>>> class MyClass:
... def __init__(self):
... self.data = set()
... self.more = dict()
... def do_stuff(self):
... return sorted(self.more)
...
>>> c = MyClass()
>>> c.data.add(1)
>>> c.data.add(2)
>>> c.data.add(3)
>>> c.data
set([1, 2, 3])
>>> c.more['1'] = 1
>>> c.more['2'] = 2
>>> c.more['3'] = lambda x:x
>>> def more_stuff(self, x):
... return x+1
...
>>> c.more_stuff = more_stuff
>>>
>>> with open('my_c.pik', "wb") as f:
... dill.dump(c, f)
...
>>>

关闭 session ,并在新 session 中重新启动...

Python 2.7.8 (default, Jul 13 2014, 02:29:54) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> with open('my_c.pik', "rb") as f:
... c = dill.load(f)
...
>>> c.data
set([1, 2, 3])
>>> c.more
{'1': 1, '3': <function <lambda> at 0x10473ec80>, '2': 2}
>>> c.do_stuff()
['1', '2', '3']
>>> c.more_stuff(5)
6

在这里获取 dill:https://github.com/uqfoundation/dill

关于python - 使用 Python pickle 存储对象,并将其加载到不同的命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26696695/

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