Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何恢复pickle类及其实例_Python_Pickle - Fatal编程技术网

Python 如何恢复pickle类及其实例

Python 如何恢复pickle类及其实例,python,pickle,Python,Pickle,我想存储一个类和许多实例,以供以后使用,或者提供给其他人 到目前为止,我可以pickle和恢复实例,但是在加载它们之前,我必须手工重新创建类 我看过一些文档,这些文档让我相信我应该能够以某种方式做到这一点,但我似乎无法确切地找到如何做到这一点 编辑:我读过这篇文章,讨论了如何使用dill(另请参见答案),但我没有安装dill。如果有的话,我想要一份泡菜溶液 import numpy as np import pickle class wow(object): def __init__(

我想存储一个类和许多实例,以供以后使用,或者提供给其他人

到目前为止,我可以pickle和恢复实例,但是在加载它们之前,我必须手工重新创建类

我看过一些文档,这些文档让我相信我应该能够以某种方式做到这一点,但我似乎无法确切地找到如何做到这一点

编辑:我读过这篇文章,讨论了如何使用
dill
(另请参见答案),但我没有安装
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文件,如前所述:


通常,如果可以对任何对象的每个属性进行pickle,则可以对该对象进行pickle不能对类、函数和方法进行pickle

资料来源:


不要销毁该类或将其作为模块导入。

我认为错误是由于您删除了该类定义造成的。Python中的对象序列化(据我所知也是Java中的对象序列化)需要类定义

从您的链接文档:

请注意,函数(内置和用户定义)是通过“完全限定”名称引用而不是通过值进行pickle的。这意味着只有函数名与定义函数的模块名一起被pickle。函数的代码及其任何函数属性都不会被pickle。因此,定义模块必须在取消勾选环境中可导入,并且该模块必须包含命名对象,否则将引发异常。[4]

类似地,类通过命名引用进行pickle,因此在取消pickle环境中应用相同的限制。请注意,类的任何代码或数据都不会被pickle


如果您想向朋友发送类和实例,请通过定义类的代码发送类,并通过pickle文件发送实例。

如果您关心安全性,dill和
pickle
都有相同的问题。但是,如果您希望易于使用,
dill
将处理您希望处理的确切案例。您可以动态创建一个类,然后使用
dill
保存它的实例……然后将实例传递到没有类定义的环境中,
dill
仍然能够重新创建该类和类实例。这是因为,与
pickle
不同,
dill
在pickle中存储类定义(默认情况下)以及类实例的状态

>>> 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

>>> 
Python 2.7.10(默认,2015年9月2日,17:36:25)
[GCC 4.2.1达尔文兼容苹果LLVM 5.1(clang-503.0.40)]
有关详细信息,请键入“帮助”、“版权”、“信用证”或“许可证”。
>>>进口莳萝
>>>以open('instance.pkl','r')作为pkl:
...   f=静载荷(pkl)
... 
>>>f
>>>f.x
1.
>>>f.z
2.
>>>打印dill.source.getsource(f.\uuuu类)
类Foo(对象):
x=1
def条(自身,y):
返回self.x+y
定义初始化(self,z):
self.z=z
>>> 

简言之,我不同意所有其他答案。您甚至在问题中链接了一个答案,该答案显示类实例、类实例状态和类代码可以被pickle

你也试过在课堂上酸洗吗<代码>pickle.dump([wow,w5,w3],outfile)是,请参见第14-16行。也尝试过你的方式,没有改变。我认为你必须使用“wb”和“rb”来二进制写入和读取文件
dill
安装
pip-install
…并且是纯python的…那么你为什么不想安装它呢?当然,作为
dill
的作者,我是有偏见的……但是有了
dill
,你就有了一个简单的问题解决方案。通过问这个问题,我学到了更多,然后理解了为什么专门pickle不会对类进行pickle。dill也有一些我还不完全理解的安全问题。本能地安装陌生人让你安装的任何东西并不总是明智的。我认为最好的解决方案是公认答案中的一个:将类作为可读的python发送,并将对象放入pickle中。对于对象,它可以按照编写的
..'w')
正常工作。对于类,
..'wb')
..'rb')
不更改错误消息
'module'对象没有属性“wow”
。这是一个明确的答案,但我试图看看它如何与文档中的bullet#7相匹配。第11.1.4节“可以对以下类型进行pickle:……在模块的顶层定义的类”,在我看来,我应该能够做到这一点。我猜应该是“你可以对你的类进行pickle,但你不能从pickle中得到你的类。”好吧,这似乎是一刀切的,谢谢!我仍然对@LaPriWa“第11.1.4节”中我对答案的评论感到不舒服,因为以下类型的问题可以解决:。。。在模块的顶层定义的类“在我看来,我应该能够做到这一点”,但我想综合起来——你可以对类进行pickle处理,但你不会得到你想要的。不客气。至于那一行,是的,看起来很混乱,我想你可以对类进行pickle,以序列化对类变量的任何运行时更改,以供以后检索。编辑:对不起,我只记得类数据也没有被pickle。不确定通过酸洗类可以获得什么,如果您想使用
pickle
而不是
dill
来做同样的事情,那么您可以。您只需使用
copyreg
注册如何通过保存代码来序列化类。这就是dill在pickle之上所做的,因此您也可以通过注册一个序列化类的定义来完成。谢谢。问题真的是关于泡菜;pickle是我键入导入pickle时导入的模块
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

>>>