How to recover a pickled class and its instances

2019-02-25 15:48发布

I would like to store a class and many instances for later use, or to give to someone else.

So far I can pickle and recover the instances, but I have to recreate the class by hand before loading them.

I've looked at this documentation which leads me to believe I should be able to do this somehow, but I can't seem to find out exactly how to do it.

EDIT: I've read this answer discussing the use of dill(see this answer also), but I don't have dill installed. I'd like a pickle solution if it exists.

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

标签: python pickle
4条回答
Viruses.
2楼-- · 2019-02-25 16:24

you must open pickle file in binary mode as it mentioned here:

with open('data.pickle', 'wb') as f:
    pickle.dump(data, f)
查看更多
神经病院院长
3楼-- · 2019-02-25 16:25

If you are concerned about security, both dill and pickle have the same issues. However, if you want ease of use, dill handles the exact case you are looking to handle. You can dynamically create a class and then save it's instance with dill… then pass the instance to an environment that doesn't have the class definition, and dill will still be able to recreate the class and the class instance. This is because, unlike pickle, dill stores the class definition in the pickle (by default) as well as the class instance's state.

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

Then ship the file to another computer… restart a session, and like magic, it works.

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

>>> 

In short, I disagree with all of the other answers. You've even linked an answer in your question that shows that class instances, class instance state, and class code can be pickled. Pickle python class instance plus definition

查看更多
Animai°情兽
4楼-- · 2019-02-25 16:34

Generally you can pickle any object if you can pickle every attribute of that object. Classes, functions, and methods cannot be pickled.

Source: https://wiki.python.org/moin/UsingPickle

Don't destroy the class or import it as a module.

查看更多
够拽才男人
5楼-- · 2019-02-25 16:38

I believe the error is caused because you deleted the class definition. Object serialization in Python (which to my knowledge is also in Java) requires the class definition to be there.

From your linked documentation:

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

If you want to send your friend the class and instances, send the class through a code defining the class wow, and the instances through the pickle file.

查看更多
登录 后发表回答