Tôi nghĩ rằng đó là một giả định khá mạnh mẽ để cho rằng đối tượng là một class
. Nếu nó không phải là một class
? Cũng có giả định rằng đối tượng không được xác định trong trình thông dịch. Điều gì nếu nó được định nghĩa trong trình thông dịch? Ngoài ra, nếu các thuộc tính được thêm động thì sao? Khi một số đối tượng python có các thuộc tính được thêm vào __dict__
sau khi tạo, pickle
chúng không tôn trọng việc thêm các thuộc tính đó (tức là 'quên' chúng đã được thêm vào - bởi vì pickle
tuần tự hóa bằng cách tham chiếu đến định nghĩa đối tượng).
Trong tất cả các trường hợp, pickle
và cPickle
có thể thất bại bạn khủng khiếp.
Nếu bạn đang tìm cách lưu object
(được tạo tùy ý), trong đó bạn có các thuộc tính (được thêm vào trong định nghĩa đối tượng hoặc sau đó), đặt cược tốt nhất của bạn là sử dụng dill
, có thể tuần tự hóa hầu hết mọi thứ trong python.
Chúng tôi bắt đầu với một lớp học
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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 pickle
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>> with open('company.pkl', 'wb') as f:
... pickle.dump(company1, f, pickle.HIGHEST_PROTOCOL)
...
>>>
Bây giờ hãy tắt và khởi động lại ...
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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 pickle
>>> with open('company.pkl', 'rb') as f:
... company1 = pickle.load(f)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1378, in load
return Unpickler(file).load()
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1090, in load_global
klass = self.find_class(module, name)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1126, in find_class
klass = getattr(mod, name)
AttributeError: 'module' object has no attribute 'Company'
>>>
Rất tiếc pickle
không thể xử lý nó. Hãy thử xem dill
. Chúng tôi sẽ ném vào một loại đối tượng khác (a lambda
) cho biện pháp tốt.
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>>
>>> company2 = lambda x:x
>>> company2.name = 'rhubarb'
>>> company2.value = 42
>>>
>>> with open('company_dill.pkl', 'wb') as f:
... dill.dump(company1, f)
... dill.dump(company2, f)
...
>>>
Và bây giờ đọc các tập tin.
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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
>>> with open('company_dill.pkl', 'rb') as f:
... company1 = dill.load(f)
... company2 = dill.load(f)
...
>>> company1
<__main__.Company instance at 0x107909128>
>>> company1.name
'banana'
>>> company1.value
40
>>> company2.name
'rhubarb'
>>> company2.value
42
>>>
Nó hoạt động. Lý do pickle
thất bại, và dill
không, là dill
đối xử __main__
như một mô-đun (đối với hầu hết các phần), và cũng có thể chọn các định nghĩa lớp thay vì chọn theo tham chiếu (như pickle
không). Lý do dill
có thể gây rắc rối lambda
là vì nó mang lại cho nó một cái tên, sau đó phép thuật ngâm có thể xảy ra.
Trên thực tế, có một cách dễ dàng hơn để lưu tất cả các đối tượng này, đặc biệt là nếu bạn có nhiều đối tượng bạn đã tạo. Chỉ cần đổ toàn bộ phiên python, và quay lại sau.
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>>
>>> company2 = lambda x:x
>>> company2.name = 'rhubarb'
>>> company2.value = 42
>>>
>>> dill.dump_session('dill.pkl')
>>>
Bây giờ hãy tắt máy tính của bạn, thưởng thức espresso hoặc bất cứ thứ gì, và quay lại sau ...
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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
>>> dill.load_session('dill.pkl')
>>> company1.name
'banana'
>>> company1.value
40
>>> company2.name
'rhubarb'
>>> company2.value
42
>>> company2
<function <lambda> at 0x1065f2938>
Hạn chế lớn duy nhất dill
là không phải là một phần của thư viện chuẩn python. Vì vậy, nếu bạn không thể cài đặt gói python trên máy chủ của mình, thì bạn không thể sử dụng nó.
Tuy nhiên, nếu bạn có thể cài đặt các gói python trên hệ thống của mình, bạn có thể nhận được bản mới nhất dill
với git+https://github.com/uqfoundation/dill.git@master#egg=dill
. Và bạn có thể nhận được phiên bản phát hành mới nhất với pip install dill
.