如何恢复 pickled class 及其实例
How to recover a pickled class and its instances
我想存储一个 class 和许多实例供以后使用,或者送给别人。
到目前为止,我可以 pickle 和恢复实例,但我必须在加载它们之前手动重新创建 class。
我查看了 this 文档,这让我相信我应该能够以某种方式做到这一点,但我似乎无法找到确切的方法。
编辑:我也读过这个 answer discussing the use of dill
(see this 答案),但我没有安装 dill
。如果有泡菜解决方案,我想要。
import numpy as np
import pickle
class wow(object):
def __init__(self, x):
self.x = x
w5 = wow(np.arange(5))
w3 = wow(range(3))
with open("w5w3.pickle", "w") as outfile:
pickle.dump([w5, w3], outfile)
# save the class also
with open("wow.pickle", "w") as outfile:
pickle.dump(wow, outfile)
# OK, now delete class wow, then try to recover the pickles
del wow, w3, w5
try:
with open("wow.pickle", "r") as infile:
wow = pickle.load(infile)
except Exception, e: # returns: "'module' object has no attribute 'wow'"
print str(e)
print "so manually recreate class wow"
class wow(object):
def __init__(self, x):
self.x = x
with open("w5w3.pickle", "r") as infile:
W = pickle.load(infile)
for thing in W:
print type(thing.x), thing.x
你必须按照上面提到的那样以二进制模式打开 pickle 文件 here:
with open('data.pickle', 'wb') as f:
pickle.dump(data, f)
通常,如果您可以 pickle 对象的每个属性,则可以 pickle 任何对象。 类,函数和方法不能被腌制。
来源:https://wiki.python.org/moin/UsingPickle
不要破坏 class 或将其作为模块导入。
我认为错误是因为您删除了 class 定义。 Python 中的对象序列化(据我所知也在 Java 中)需要 class 定义。
来自您的链接文档:
Note that functions (built-in and user-defined) are pickled by “fully qualified” name reference, not by value. This means that only the function name is pickled, along with the name of the module the function is defined in. Neither the function’s code, nor any of its function attributes are pickled. Thus the defining module must be importable in the unpickling environment, and the module must contain the named object, otherwise an exception will be raised. [4]
Similarly, classes are pickled by named reference, so the same restrictions in the unpickling environment apply. Note that none of the class’s code or data is pickled
如果您想向朋友发送 class 和实例,请通过定义 class wow
的代码发送 class,并通过 pickle 发送实例文件。
如果您担心安全问题,dill
和 pickle
都有相同的问题。但是,如果您希望易于使用,dill
可以处理您希望处理的确切情况。您可以动态创建一个 class 然后用 dill
保存它的实例...然后将实例传递到没有 class 定义的环境,并且 dill
仍然会能够重新创建 class 和 class 实例。这是因为,与 pickle
不同,dill
将 class 定义存储在泡菜中(默认情况下)以及 class 实例的状态。
>>> class Foo(object):
... x = 1
... def bar(self, y):
... return self.x + y
... def __init__(self, z):
... self.z = z
...
>>> f = Foo(2)
>>> import dill
>>> with open('instance.pkl', 'w') as pkl:
... dill.dump(f, pkl)
...
>>>
然后将文件发送到另一台计算机...重新启动会话,就像变魔术一样,它成功了。
Python 2.7.10 (default, Sep 2 2015, 17:36:25)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> with open('instance.pkl', 'r') as pkl:
... f = dill.load(pkl)
...
>>> f
<__main__.Foo object at 0x10eb4a450>
>>> f.x
1
>>> f.z
2
>>> print dill.source.getsource(f.__class__)
class Foo(object):
x = 1
def bar(self, y):
return self.x + y
def __init__(self, z):
self.z = z
>>>
简而言之,我不同意所有其他答案。您甚至在问题中链接了一个答案,表明 class 实例、class 实例状态和 class 代码 可以 被腌制。 Pickle python class instance plus definition
我想存储一个 class 和许多实例供以后使用,或者送给别人。
到目前为止,我可以 pickle 和恢复实例,但我必须在加载它们之前手动重新创建 class。
我查看了 this 文档,这让我相信我应该能够以某种方式做到这一点,但我似乎无法找到确切的方法。
编辑:我也读过这个 answer discussing the use of dill
(see this 答案),但我没有安装 dill
。如果有泡菜解决方案,我想要。
import numpy as np
import pickle
class wow(object):
def __init__(self, x):
self.x = x
w5 = wow(np.arange(5))
w3 = wow(range(3))
with open("w5w3.pickle", "w") as outfile:
pickle.dump([w5, w3], outfile)
# save the class also
with open("wow.pickle", "w") as outfile:
pickle.dump(wow, outfile)
# OK, now delete class wow, then try to recover the pickles
del wow, w3, w5
try:
with open("wow.pickle", "r") as infile:
wow = pickle.load(infile)
except Exception, e: # returns: "'module' object has no attribute 'wow'"
print str(e)
print "so manually recreate class wow"
class wow(object):
def __init__(self, x):
self.x = x
with open("w5w3.pickle", "r") as infile:
W = pickle.load(infile)
for thing in W:
print type(thing.x), thing.x
你必须按照上面提到的那样以二进制模式打开 pickle 文件 here:
with open('data.pickle', 'wb') as f:
pickle.dump(data, f)
通常,如果您可以 pickle 对象的每个属性,则可以 pickle 任何对象。 类,函数和方法不能被腌制。
来源:https://wiki.python.org/moin/UsingPickle
不要破坏 class 或将其作为模块导入。
我认为错误是因为您删除了 class 定义。 Python 中的对象序列化(据我所知也在 Java 中)需要 class 定义。
来自您的链接文档:
Note that functions (built-in and user-defined) are pickled by “fully qualified” name reference, not by value. This means that only the function name is pickled, along with the name of the module the function is defined in. Neither the function’s code, nor any of its function attributes are pickled. Thus the defining module must be importable in the unpickling environment, and the module must contain the named object, otherwise an exception will be raised. [4]
Similarly, classes are pickled by named reference, so the same restrictions in the unpickling environment apply. Note that none of the class’s code or data is pickled
如果您想向朋友发送 class 和实例,请通过定义 class wow
的代码发送 class,并通过 pickle 发送实例文件。
如果您担心安全问题,dill
和 pickle
都有相同的问题。但是,如果您希望易于使用,dill
可以处理您希望处理的确切情况。您可以动态创建一个 class 然后用 dill
保存它的实例...然后将实例传递到没有 class 定义的环境,并且 dill
仍然会能够重新创建 class 和 class 实例。这是因为,与 pickle
不同,dill
将 class 定义存储在泡菜中(默认情况下)以及 class 实例的状态。
>>> class Foo(object):
... x = 1
... def bar(self, y):
... return self.x + y
... def __init__(self, z):
... self.z = z
...
>>> f = Foo(2)
>>> import dill
>>> with open('instance.pkl', 'w') as pkl:
... dill.dump(f, pkl)
...
>>>
然后将文件发送到另一台计算机...重新启动会话,就像变魔术一样,它成功了。
Python 2.7.10 (default, Sep 2 2015, 17:36:25)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> with open('instance.pkl', 'r') as pkl:
... f = dill.load(pkl)
...
>>> f
<__main__.Foo object at 0x10eb4a450>
>>> f.x
1
>>> f.z
2
>>> print dill.source.getsource(f.__class__)
class Foo(object):
x = 1
def bar(self, y):
return self.x + y
def __init__(self, z):
self.z = z
>>>
简而言之,我不同意所有其他答案。您甚至在问题中链接了一个答案,表明 class 实例、class 实例状态和 class 代码 可以 被腌制。 Pickle python class instance plus definition