Pickle Dump 在 class 中保存一个对象
Pickle Dump to save an object within the class
假设我有一个像这样的 class:-
class MyClass:
some object here
some other object here
def init(self, some parameters):
do something
def some_other_method(self, param):
something else
def save(self, path):
PICKLE DUMP THIS OBJECT
def load(self, path):
PICKLE LOAD OBJECT
我不想像这样 pickle 加载和转储:
obj = MyClass(param)
pickle.dump(obj, mypath)
而是像这样:
obj.save(mypath)
如何在 class 定义中执行此操作?
您可以传递 self
而不是 obj
。换句话说:
def save(self, file_handler):
pickle.dump(self, file_handler)
self
指向 class 的实例。所以你基本上做的是调用 pickle.dump
并将实例与 file_handler
参数一起传递给它。
让我们构建一个 class A
,然后尝试...
>>> class A(object):
... x = 1
... def __init__(self, y):
... self.y = y
... def showme(self):
... return self.y + self.x
... def save(self):
... return pickle.dump(self)
... def load(self, pik):
... self.__dict__.update(pickle.loads(pik).__dict__)
...
>>> a = A(2)
>>> a.showme()
3
>>> import pickle
>>>
>>> a_ = a.save()
>>> a.y = 5
>>> a.showme()
6
>>> a.load(a_)
>>> a.y
2
>>> a.showme()
3
>>> b = A(9)
>>> b.load(a_)
>>> b.y
2
>>> b.showme()
3
>>> b.x = 4
>>> b.showme()
6
>>> b_ = b.save()
>>> a.load(b_)
>>> a.x
4
>>> a.y
2
>>> a.showme()
6
>>>
但是,由于您在 __main__
中定义了 class,如果您要重新开始 python 解释器会话……您的泡菜将毫无用处,因为 class将不复存在。那是因为 python 通过引用腌制。但是,有一个解决方法。如果您使用 dill
,您也可以通过序列化 class 定义来 pickle 您的 classes。然后在 __main__
中定义的 classes 在新会话中仍然可用。
>>> a.showme()
6
>>> import dill as pickle
>>> a.save()
'\x80\x02cdill.dill\n_create_type\nq\x00(cdill.dill\n_load_type\nq\x01U\x08TypeTypeq\x02\x85q\x03Rq\x04U\x01Aq\x05h\x01U\nObjectTypeq\x06\x85q\x07Rq\x08\x85q\t}q\n(U\x04loadq\x0bcdill.dill\n_create_function\nq\x0c(cdill.dill\n_unmarshal\nq\rU\xaec\x02\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00C\x00\x00\x00s \x00\x00\x00|\x00\x00j\x00\x00j\x01\x00t\x02\x00j\x03\x00|\x01\x00\x83\x01\x00j\x00\x00\x83\x01\x00\x01d\x00\x00S(\x01\x00\x00\x00N(\x04\x00\x00\x00t\x08\x00\x00\x00__dict__t\x06\x00\x00\x00updatet\x06\x00\x00\x00picklet\x05\x00\x00\x00loads(\x02\x00\x00\x00t\x04\x00\x00\x00selft\x03\x00\x00\x00pik(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x04\x00\x00\x00load\t\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x0e\x85q\x0fRq\x10c__builtin__\n__main__\nh\x0bNN}q\x11tq\x12Rq\x13U\r__slotnames__q\x14]q\x15U\n__module__q\x16U\x08__main__q\x17U\x06showmeq\x18h\x0c(h\rUuc\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\x0e\x00\x00\x00|\x00\x00j\x00\x00|\x00\x00j\x01\x00\x17S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x01\x00\x00\x00yt\x01\x00\x00\x00x(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x06\x00\x00\x00showme\x05\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x19\x85q\x1aRq\x1bc__builtin__\n__main__\nh\x18NN}q\x1ctq\x1dRq\x1eU\x01xq\x1fK\x01U\x04saveq h\x0c(h\rU{c\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00t\x00\x00j\x01\x00|\x00\x00\x83\x01\x00S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x06\x00\x00\x00picklet\x05\x00\x00\x00dumps(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x04\x00\x00\x00save\x07\x00\x00\x00s\x02\x00\x00\x00\x00\x01q!\x85q"Rq#c__builtin__\n__main__\nh NN}q$tq%Rq&U\x07__doc__q\'NU\x08__init__q(h\x0c(h\rUuc\x02\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00|\x01\x00|\x00\x00_\x00\x00d\x00\x00S(\x01\x00\x00\x00N(\x01\x00\x00\x00t\x01\x00\x00\x00y(\x02\x00\x00\x00t\x04\x00\x00\x00selfR\x00\x00\x00\x00(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x08\x00\x00\x00__init__\x03\x00\x00\x00s\x02\x00\x00\x00\x00\x01q)\x85q*Rq+c__builtin__\n__main__\nh(NN}q,tq-Rq.utq/Rq0)\x81q1}q2(U\x01yq3K\x02h\x1fK\x04ub.'
>>>
然后我们退出会话,然后重新启动。从上面粘贴字符串。
(是的,我可以改用文件句柄,但稍后我会展示它……)
Python 2.7.9 (default, Dec 11 2014, 01:21:43)
[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 as pickle
>>>
>>> a = '\x80\x02cdill.dill\n_create_type\nq\x00(cdill.dill\n_load_type\nq\x01U\x08TypeTypeq\x02\x85q\x03Rq\x04U\x01Aq\x05h\x01U\nObjectTypeq\x06\x85q\x07Rq\x08\x85q\t}q\n(U\x04loadq\x0bcdill.dill\n_create_function\nq\x0c(cdill.dill\n_unmarshal\nq\rU\xaec\x02\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00C\x00\x00\x00s \x00\x00\x00|\x00\x00j\x00\x00j\x01\x00t\x02\x00j\x03\x00|\x01\x00\x83\x01\x00j\x00\x00\x83\x01\x00\x01d\x00\x00S(\x01\x00\x00\x00N(\x04\x00\x00\x00t\x08\x00\x00\x00__dict__t\x06\x00\x00\x00updatet\x06\x00\x00\x00picklet\x05\x00\x00\x00loads(\x02\x00\x00\x00t\x04\x00\x00\x00selft\x03\x00\x00\x00pik(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x04\x00\x00\x00load\t\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x0e\x85q\x0fRq\x10c__builtin__\n__main__\nh\x0bNN}q\x11tq\x12Rq\x13U\r__slotnames__q\x14]q\x15U\n__module__q\x16U\x08__main__q\x17U\x06showmeq\x18h\x0c(h\rUuc\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\x0e\x00\x00\x00|\x00\x00j\x00\x00|\x00\x00j\x01\x00\x17S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x01\x00\x00\x00yt\x01\x00\x00\x00x(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x06\x00\x00\x00showme\x05\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x19\x85q\x1aRq\x1bc__builtin__\n__main__\nh\x18NN}q\x1ctq\x1dRq\x1eU\x01xq\x1fK\x01U\x04saveq h\x0c(h\rU{c\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00t\x00\x00j\x01\x00|\x00\x00\x83\x01\x00S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x06\x00\x00\x00picklet\x05\x00\x00\x00dumps(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x04\x00\x00\x00save\x07\x00\x00\x00s\x02\x00\x00\x00\x00\x01q!\x85q"Rq#c__builtin__\n__main__\nh NN}q$tq%Rq&U\x07__doc__q\'NU\x08__init__q(h\x0c(h\rUuc\x02\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00|\x01\x00|\x00\x00_\x00\x00d\x00\x00S(\x01\x00\x00\x00N(\x01\x00\x00\x00t\x01\x00\x00\x00y(\x02\x00\x00\x00t\x04\x00\x00\x00selfR\x00\x00\x00\x00(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x08\x00\x00\x00__init__\x03\x00\x00\x00s\x02\x00\x00\x00\x00\x01q)\x85q*Rq+c__builtin__\n__main__\nh(NN}q,tq-Rq.utq/Rq0)\x81q1}q2(U\x01yq3K\x02h\x1fK\x04ub.'
>>>
>>> pickle.loads(a)
<__main__.A object at 0x105691c50>
>>> b = _
>>>
>>> b.x
4
>>> b.showme()
6
>>> A = b.__class__
>>> c = A(2)
>>> c.x
1
>>> c.showme()
3
令人难以置信的是,class 是在 __main__
中从 pickled 实例中重建的。好的,现在,让我们开始更改 class 方法以使用新的 save
和 load
来处理文件而不是字符串。
>>> def save(self, path):
... with open(path, 'w') as f:
... pickle.dump(self, f)
...
>>> def load(self, path):
... with open(path, 'r') as f:
... self.__dict__.update(pickle.load(f).__dict__)
...
>>> A.save = save
>>> A.load = load
>>>
>>> c.save('foo')
>>>
然后我们退出会话并重新启动。由于我们没有 A
的版本,我们必须直接从 pickle
使用 load
方法(实际上,在这种情况下是 dill
)。
Python 2.7.9 (default, Dec 11 2014, 01:21:43)
[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 as pickle
>>> with open('foo', 'r') as f:
... a = pickle.load(f)
...
>>> a
<__main__.A object at 0x1028c0b10>
>>> a.x
1
>>> a.showme()
3
>>> a.y = 6
>>> a.showme()
7
>>> a.load('foo')
>>> a.y
2
>>> a.showme()
3
>>>
可能有更好或更具体的方法,您可能希望加载 class 实例的状态,而不是更新 __dict__
。这样做并非在所有情况下都有效,最好根据您的 class 进行自定义。但是,如果是我,我不会在 class 中使用 save
和 load
方法,而是会直接使用序列化程序提供的方法。您可以在上面看到 awkward/redundant 如何使用 class.
中的 load
方法
假设我有一个像这样的 class:-
class MyClass:
some object here
some other object here
def init(self, some parameters):
do something
def some_other_method(self, param):
something else
def save(self, path):
PICKLE DUMP THIS OBJECT
def load(self, path):
PICKLE LOAD OBJECT
我不想像这样 pickle 加载和转储:
obj = MyClass(param)
pickle.dump(obj, mypath)
而是像这样:
obj.save(mypath)
如何在 class 定义中执行此操作?
您可以传递 self
而不是 obj
。换句话说:
def save(self, file_handler):
pickle.dump(self, file_handler)
self
指向 class 的实例。所以你基本上做的是调用 pickle.dump
并将实例与 file_handler
参数一起传递给它。
让我们构建一个 class A
,然后尝试...
>>> class A(object):
... x = 1
... def __init__(self, y):
... self.y = y
... def showme(self):
... return self.y + self.x
... def save(self):
... return pickle.dump(self)
... def load(self, pik):
... self.__dict__.update(pickle.loads(pik).__dict__)
...
>>> a = A(2)
>>> a.showme()
3
>>> import pickle
>>>
>>> a_ = a.save()
>>> a.y = 5
>>> a.showme()
6
>>> a.load(a_)
>>> a.y
2
>>> a.showme()
3
>>> b = A(9)
>>> b.load(a_)
>>> b.y
2
>>> b.showme()
3
>>> b.x = 4
>>> b.showme()
6
>>> b_ = b.save()
>>> a.load(b_)
>>> a.x
4
>>> a.y
2
>>> a.showme()
6
>>>
但是,由于您在 __main__
中定义了 class,如果您要重新开始 python 解释器会话……您的泡菜将毫无用处,因为 class将不复存在。那是因为 python 通过引用腌制。但是,有一个解决方法。如果您使用 dill
,您也可以通过序列化 class 定义来 pickle 您的 classes。然后在 __main__
中定义的 classes 在新会话中仍然可用。
>>> a.showme()
6
>>> import dill as pickle
>>> a.save()
'\x80\x02cdill.dill\n_create_type\nq\x00(cdill.dill\n_load_type\nq\x01U\x08TypeTypeq\x02\x85q\x03Rq\x04U\x01Aq\x05h\x01U\nObjectTypeq\x06\x85q\x07Rq\x08\x85q\t}q\n(U\x04loadq\x0bcdill.dill\n_create_function\nq\x0c(cdill.dill\n_unmarshal\nq\rU\xaec\x02\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00C\x00\x00\x00s \x00\x00\x00|\x00\x00j\x00\x00j\x01\x00t\x02\x00j\x03\x00|\x01\x00\x83\x01\x00j\x00\x00\x83\x01\x00\x01d\x00\x00S(\x01\x00\x00\x00N(\x04\x00\x00\x00t\x08\x00\x00\x00__dict__t\x06\x00\x00\x00updatet\x06\x00\x00\x00picklet\x05\x00\x00\x00loads(\x02\x00\x00\x00t\x04\x00\x00\x00selft\x03\x00\x00\x00pik(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x04\x00\x00\x00load\t\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x0e\x85q\x0fRq\x10c__builtin__\n__main__\nh\x0bNN}q\x11tq\x12Rq\x13U\r__slotnames__q\x14]q\x15U\n__module__q\x16U\x08__main__q\x17U\x06showmeq\x18h\x0c(h\rUuc\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\x0e\x00\x00\x00|\x00\x00j\x00\x00|\x00\x00j\x01\x00\x17S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x01\x00\x00\x00yt\x01\x00\x00\x00x(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x06\x00\x00\x00showme\x05\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x19\x85q\x1aRq\x1bc__builtin__\n__main__\nh\x18NN}q\x1ctq\x1dRq\x1eU\x01xq\x1fK\x01U\x04saveq h\x0c(h\rU{c\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00t\x00\x00j\x01\x00|\x00\x00\x83\x01\x00S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x06\x00\x00\x00picklet\x05\x00\x00\x00dumps(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x04\x00\x00\x00save\x07\x00\x00\x00s\x02\x00\x00\x00\x00\x01q!\x85q"Rq#c__builtin__\n__main__\nh NN}q$tq%Rq&U\x07__doc__q\'NU\x08__init__q(h\x0c(h\rUuc\x02\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00|\x01\x00|\x00\x00_\x00\x00d\x00\x00S(\x01\x00\x00\x00N(\x01\x00\x00\x00t\x01\x00\x00\x00y(\x02\x00\x00\x00t\x04\x00\x00\x00selfR\x00\x00\x00\x00(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x08\x00\x00\x00__init__\x03\x00\x00\x00s\x02\x00\x00\x00\x00\x01q)\x85q*Rq+c__builtin__\n__main__\nh(NN}q,tq-Rq.utq/Rq0)\x81q1}q2(U\x01yq3K\x02h\x1fK\x04ub.'
>>>
然后我们退出会话,然后重新启动。从上面粘贴字符串。 (是的,我可以改用文件句柄,但稍后我会展示它……)
Python 2.7.9 (default, Dec 11 2014, 01:21:43)
[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 as pickle
>>>
>>> a = '\x80\x02cdill.dill\n_create_type\nq\x00(cdill.dill\n_load_type\nq\x01U\x08TypeTypeq\x02\x85q\x03Rq\x04U\x01Aq\x05h\x01U\nObjectTypeq\x06\x85q\x07Rq\x08\x85q\t}q\n(U\x04loadq\x0bcdill.dill\n_create_function\nq\x0c(cdill.dill\n_unmarshal\nq\rU\xaec\x02\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00C\x00\x00\x00s \x00\x00\x00|\x00\x00j\x00\x00j\x01\x00t\x02\x00j\x03\x00|\x01\x00\x83\x01\x00j\x00\x00\x83\x01\x00\x01d\x00\x00S(\x01\x00\x00\x00N(\x04\x00\x00\x00t\x08\x00\x00\x00__dict__t\x06\x00\x00\x00updatet\x06\x00\x00\x00picklet\x05\x00\x00\x00loads(\x02\x00\x00\x00t\x04\x00\x00\x00selft\x03\x00\x00\x00pik(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x04\x00\x00\x00load\t\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x0e\x85q\x0fRq\x10c__builtin__\n__main__\nh\x0bNN}q\x11tq\x12Rq\x13U\r__slotnames__q\x14]q\x15U\n__module__q\x16U\x08__main__q\x17U\x06showmeq\x18h\x0c(h\rUuc\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\x0e\x00\x00\x00|\x00\x00j\x00\x00|\x00\x00j\x01\x00\x17S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x01\x00\x00\x00yt\x01\x00\x00\x00x(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x06\x00\x00\x00showme\x05\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x19\x85q\x1aRq\x1bc__builtin__\n__main__\nh\x18NN}q\x1ctq\x1dRq\x1eU\x01xq\x1fK\x01U\x04saveq h\x0c(h\rU{c\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00t\x00\x00j\x01\x00|\x00\x00\x83\x01\x00S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x06\x00\x00\x00picklet\x05\x00\x00\x00dumps(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x04\x00\x00\x00save\x07\x00\x00\x00s\x02\x00\x00\x00\x00\x01q!\x85q"Rq#c__builtin__\n__main__\nh NN}q$tq%Rq&U\x07__doc__q\'NU\x08__init__q(h\x0c(h\rUuc\x02\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00|\x01\x00|\x00\x00_\x00\x00d\x00\x00S(\x01\x00\x00\x00N(\x01\x00\x00\x00t\x01\x00\x00\x00y(\x02\x00\x00\x00t\x04\x00\x00\x00selfR\x00\x00\x00\x00(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x08\x00\x00\x00__init__\x03\x00\x00\x00s\x02\x00\x00\x00\x00\x01q)\x85q*Rq+c__builtin__\n__main__\nh(NN}q,tq-Rq.utq/Rq0)\x81q1}q2(U\x01yq3K\x02h\x1fK\x04ub.'
>>>
>>> pickle.loads(a)
<__main__.A object at 0x105691c50>
>>> b = _
>>>
>>> b.x
4
>>> b.showme()
6
>>> A = b.__class__
>>> c = A(2)
>>> c.x
1
>>> c.showme()
3
令人难以置信的是,class 是在 __main__
中从 pickled 实例中重建的。好的,现在,让我们开始更改 class 方法以使用新的 save
和 load
来处理文件而不是字符串。
>>> def save(self, path):
... with open(path, 'w') as f:
... pickle.dump(self, f)
...
>>> def load(self, path):
... with open(path, 'r') as f:
... self.__dict__.update(pickle.load(f).__dict__)
...
>>> A.save = save
>>> A.load = load
>>>
>>> c.save('foo')
>>>
然后我们退出会话并重新启动。由于我们没有 A
的版本,我们必须直接从 pickle
使用 load
方法(实际上,在这种情况下是 dill
)。
Python 2.7.9 (default, Dec 11 2014, 01:21:43)
[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 as pickle
>>> with open('foo', 'r') as f:
... a = pickle.load(f)
...
>>> a
<__main__.A object at 0x1028c0b10>
>>> a.x
1
>>> a.showme()
3
>>> a.y = 6
>>> a.showme()
7
>>> a.load('foo')
>>> a.y
2
>>> a.showme()
3
>>>
可能有更好或更具体的方法,您可能希望加载 class 实例的状态,而不是更新 __dict__
。这样做并非在所有情况下都有效,最好根据您的 class 进行自定义。但是,如果是我,我不会在 class 中使用 save
和 load
方法,而是会直接使用序列化程序提供的方法。您可以在上面看到 awkward/redundant 如何使用 class.
load
方法