在 Python 中腌制 class 个实例的字典
Pickle a dictionary of class instances in Python
如何 pickle
一个字典对象,该对象在一个文件(Python 文件 1)中包含 Class 的实例,而在另一个文件 (Python 文件 2)?
我有一个由多个文件组成的巨大的复杂数据集,我创建了一个 class 来存储我的所有属性。我做了一个字典来存储所有的样本和属性。 key = sample,value = class 包含属性的实例。示例如下:
#Python File 1
import random
class Storage:
def __init__(self,label,x,y):
self.label = label; self.x = x; self.y = y
def get_x(self): return(self.x)
def get_y(self): return(self.y)
D_var_instance = {}
L = ["A","B","C"]
for var in L:
D_var_instance[var] = Storage(label=var,x=random.random(),y=random.random())
print(D_var_instance["A"])
#<__main__.Storage instance at 0x102811128>
print(D_var_instance["A"].get_x())
#0.193517721574
用我的真实数据集做这个花了我很长时间,我尝试使用 pickle
和 pickle.dump
字典对象,但它不起作用:
#Python File 1
import pickle
pickle.dump(D_var_instance,open("/path/to/dump.txt","w"))
pickle.dump(Storage, open("/path/to/storagedump.txt","w"))
我尝试使用以下代码加载另一个 Python 文件:
#Python File 2
import pickle
Storage = pickle.load(open("/path/to/storagedump.txt","r"))
D_var_instance = pickle.load(open("/path/to/dump.txt","r"))
遇到这个错误:
AttributeError: 'module' object has no attribute 'Storage'
这里的问题可以通过这个SO完美解释post对
最终,这里发生的事情是,当您对实例进行 pickle 时,您必须能够根据 pickle 的来源适当地引用您的模块。
因此,展示一些代码来说明这一点。你可以这样做(解释如下):
storage.py
class Storage(object):
pass
foo.py
import pickle
from storage import Storage
D_var_instance = {}
L = ["A","B","C"]
for var in L:
D_var_instance[var] = Storage(label=var,x=random.random(),y=random.random())
pickle.dump(D_var_instance, open("/path/pickle.txt", "wb"))
boo.py
D_var_instance = pickle.load(open("/path/pickle.txt", "rb"))
因此,当您从 foo 编写 pickle 时,您的引用现在将是 storage.Storage
。当您进入一个完全不同的模块 (boo.py) 并尝试取消 pickle 时,这里发生的是您正在尝试加载一些参考模块的内容,而该模块在您执行此操作的位置不起作用.
现在可以通过不同的方式来解决这个问题。由于我在同一级别构建了所有内容,因此您实际上不需要导入任何内容,它应该可以工作!
但是,如果您碰巧在同一个模块中编写 class 和 pickle,就像您所做的那样,那么您将必须导入包含该代码的模块 boo.py
我建议你看看我链接的SO post中提供的两个选项,看看哪个让你满意。但这应该是您的解决方案。
运行 来自 iPython 的这个脚本产生:
ipython boo.py
{'A': <storage.Storage instance at 0x1107b77e8>, 'C': <storage.Storage instance at 0x1107b7680>, 'B': <storage.Storage instance at 0x1107b7908>}
您可以使用 dill
而不是 pickle
来减轻自己的负担。 dill
腌制 class 定义以及 class 个实例(而不是像 pickle
那样通过引用)。因此,除了 import dill as pickle
.
之外,您不需要做任何不同的事情
为了模拟在另一个文件中工作,我将在字典中构建一个 class,一些 class 实例,然后删除除 pickled 字符串之外的所有内容。你可以从那里重组。
>>> class Foo(object):
... def __init__(self, x):
... self.x = x
...
>>> d = dict(f=Foo(1), g=Foo(2), h=Foo(3))
>>>
>>> import dill
>>> _stored_ = dill.dumps(d)
>>>
>>> del Foo
>>> del d
>>>
>>> d = dill.loads(_stored_)
>>> d['f'].x
1
>>> d['g'].x
2
>>> d['h'].x
3
>>> dill.dump_session()
我以 dump_session
结束,将解释器中的所有内容腌制到一个文件中。然后,在新的 python 会话中(可能在不同的机器上),您可以从中断的地方开始。
>>> import dill
>>> dill.load_session()
>>> d
{'h': <__main__.Foo object at 0x110c6cfd0>, 'g': <__main__.Foo object at 0x10fbce410>, 'f': <__main__.Foo object at 0x110c6b050>}
>>>
如果您正在寻找传统的 dump
和 load
,那也行。它也适用于 ipython
.
如何 pickle
一个字典对象,该对象在一个文件(Python 文件 1)中包含 Class 的实例,而在另一个文件 (Python 文件 2)?
我有一个由多个文件组成的巨大的复杂数据集,我创建了一个 class 来存储我的所有属性。我做了一个字典来存储所有的样本和属性。 key = sample,value = class 包含属性的实例。示例如下:
#Python File 1
import random
class Storage:
def __init__(self,label,x,y):
self.label = label; self.x = x; self.y = y
def get_x(self): return(self.x)
def get_y(self): return(self.y)
D_var_instance = {}
L = ["A","B","C"]
for var in L:
D_var_instance[var] = Storage(label=var,x=random.random(),y=random.random())
print(D_var_instance["A"])
#<__main__.Storage instance at 0x102811128>
print(D_var_instance["A"].get_x())
#0.193517721574
用我的真实数据集做这个花了我很长时间,我尝试使用 pickle
和 pickle.dump
字典对象,但它不起作用:
#Python File 1
import pickle
pickle.dump(D_var_instance,open("/path/to/dump.txt","w"))
pickle.dump(Storage, open("/path/to/storagedump.txt","w"))
我尝试使用以下代码加载另一个 Python 文件:
#Python File 2
import pickle
Storage = pickle.load(open("/path/to/storagedump.txt","r"))
D_var_instance = pickle.load(open("/path/to/dump.txt","r"))
遇到这个错误:
AttributeError: 'module' object has no attribute 'Storage'
这里的问题可以通过这个SO完美解释post对
最终,这里发生的事情是,当您对实例进行 pickle 时,您必须能够根据 pickle 的来源适当地引用您的模块。
因此,展示一些代码来说明这一点。你可以这样做(解释如下):
storage.py
class Storage(object):
pass
foo.py
import pickle
from storage import Storage
D_var_instance = {}
L = ["A","B","C"]
for var in L:
D_var_instance[var] = Storage(label=var,x=random.random(),y=random.random())
pickle.dump(D_var_instance, open("/path/pickle.txt", "wb"))
boo.py
D_var_instance = pickle.load(open("/path/pickle.txt", "rb"))
因此,当您从 foo 编写 pickle 时,您的引用现在将是 storage.Storage
。当您进入一个完全不同的模块 (boo.py) 并尝试取消 pickle 时,这里发生的是您正在尝试加载一些参考模块的内容,而该模块在您执行此操作的位置不起作用.
现在可以通过不同的方式来解决这个问题。由于我在同一级别构建了所有内容,因此您实际上不需要导入任何内容,它应该可以工作!
但是,如果您碰巧在同一个模块中编写 class 和 pickle,就像您所做的那样,那么您将必须导入包含该代码的模块 boo.py
我建议你看看我链接的SO post中提供的两个选项,看看哪个让你满意。但这应该是您的解决方案。
运行 来自 iPython 的这个脚本产生:
ipython boo.py
{'A': <storage.Storage instance at 0x1107b77e8>, 'C': <storage.Storage instance at 0x1107b7680>, 'B': <storage.Storage instance at 0x1107b7908>}
您可以使用 dill
而不是 pickle
来减轻自己的负担。 dill
腌制 class 定义以及 class 个实例(而不是像 pickle
那样通过引用)。因此,除了 import dill as pickle
.
为了模拟在另一个文件中工作,我将在字典中构建一个 class,一些 class 实例,然后删除除 pickled 字符串之外的所有内容。你可以从那里重组。
>>> class Foo(object):
... def __init__(self, x):
... self.x = x
...
>>> d = dict(f=Foo(1), g=Foo(2), h=Foo(3))
>>>
>>> import dill
>>> _stored_ = dill.dumps(d)
>>>
>>> del Foo
>>> del d
>>>
>>> d = dill.loads(_stored_)
>>> d['f'].x
1
>>> d['g'].x
2
>>> d['h'].x
3
>>> dill.dump_session()
我以 dump_session
结束,将解释器中的所有内容腌制到一个文件中。然后,在新的 python 会话中(可能在不同的机器上),您可以从中断的地方开始。
>>> import dill
>>> dill.load_session()
>>> d
{'h': <__main__.Foo object at 0x110c6cfd0>, 'g': <__main__.Foo object at 0x10fbce410>, 'f': <__main__.Foo object at 0x110c6b050>}
>>>
如果您正在寻找传统的 dump
和 load
,那也行。它也适用于 ipython
.