2014-09-01 15 views
9

Trong câu trả lời cho Python pickle: dealing with updated class definitions, tác giả của gói dill viết:.Làm thế nào để sử dụng thì là để tuần tự hóa một định nghĩa lớp?

"Ok, tôi đã thêm tính năng này để Dill trong phiên bản mới nhất trên github thực hiện với ít thủ đoạn gian trá hơn tôi nghĩ ... chỉ serialize định nghĩa lớp với dưa chua, và thì đấy. "

Sau khi cài đặt dill và được lưu trữ với nó, điều đó không rõ ràng đối với tôi cách thực sự sử dụng chức năng này trong dill. Ai đó có thể cung cấp một ví dụ rõ ràng? Tôi muốn pickle dụ class và cũng serialize định nghĩa lớp.

(Tôi mới sử dụng python và chức năng này có vẻ cực kỳ quan trọng, vì khi chọn một đối tượng, sẽ rất tuyệt để có được sự bảo đảm nhất có thể mà bạn có thể nhìn vào đối tượng (có thể là kết quả của một mô phỏng) trong tương lai sau khi định nghĩa lớp có thể đã thay đổi và bạn không theo dõi tất cả các thay đổi theo cách dễ dàng truy cập.)

Trả lời

3

Nếu chức năng này quan trọng, nó sẽ nằm trong lõi ngôn ngữ của hiện nay. :-) Vì vậy, không, điều này không quan trọng khi sử dụng Python dưới bất kỳ hình thức nâng cao nào - và nếu bạn có dự án dựa trên việc có thể tái tạo lại các đối tượng dựa trên các mô hình cũ - điều đó là có thể, bạn phải suy nghĩ cẩn thận về nó, và có thể giữ cho các mô hình cũ xung quanh trong mã rõ ràng, thay vì sau đó được nối tiếp.

Lời khuyên của tôi chỉ là "rời xa nhau" cho đến khi bạn nghĩ rằng bạn thực sự cần nó và so sánh nó với các giải pháp khác, như chính sách di chuyển mô hình mạnh mẽ.

Điều đó nói rằng, tôi đã thử, và nó hoạt động như được quảng cáo: nó có thể tuần tự hóa một lớp giống như dưa chuột có thể làm với các đối tượng thông thường bằng cách sử dụng lệnh "dump" và "dumps", và xây dựng lại đối tượng lớp "tải" và "tải".

Điều gì có thể khiến bạn bối rối là việc sắp xếp một đối tượng (thông qua pickle hoặc là giống nhau) không bao gồm cả mã nguồn của nó (tức là dòng mã Python thực tế được sử dụng để xác định lớp), cũng không phải tên của nó. Vì vậy, nếu một lớp được đặt tên là "A", khi nó được sắp xếp theo thứ tự, nếu bạn cần tên đó sau khi "hoàn thành" nó, bạn phải gán lại tên đó cho nó trong không gian tên chung. Tên gốc của nó được giữ nguyên trong thuộc tính __name__. (và cho mục đích của bạn của nhiều phiên bản của cùng một mô hình sống với nhau, điều đó sẽ dẫn đến rất nhiều xung đột).

Như vậy:

class A(object): 
    ... 

import dill 

dill.dump(A, open("myfile", "w")) 

del A 
.... 
someclass = dill.load(open("myfile")) 
print (someclass.__name__) 
globals()[someclass.__name__] = someclass 
# at this point you have the "A" class back in the global namespace 
4

Tôi nghĩ rằng bạn đang tìm kiếm một trong những chức năng sau ...

Ở đây tôi xây dựng một lớp học, và một thể hiện, và sau đó thay đổi định nghĩa lớp. Lớp và trường hợp đã chọn vẫn không thể đọc được vìdưa chua mã nguồn cho lớp theo mặc định ... và quản lý có một số lớp có cùng tên trong không gian tên (điều này đơn giản bằng cách quản lý con trỏ tham chiếu đến định nghĩa 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 dill 
>>> 
>>> class Foo(object): 
... def bar(self, x): 
...  return x+self.y  
... y = 1 
... 
>>> f = Foo() 
>>> _Foo = dill.dumps(Foo) 
>>> _f = dill.dumps(f) 
>>> 
>>> class Foo(object): 
... def bar(self, x): 
...  return x*self.z 
... z = -1 
... 
>>> f_ = dill.loads(_f) 
>>> f_.y 
1 
>>> f_.bar(1) 
2 
>>> Foo_ = dill.loads(_Foo) 
>>> g = Foo_() 
>>> g.bar(1) 
2 

Pickle sẽ nổ tung ở trên.Nếu bạn không muốn dill serialize lớp một cách rõ ràng, và để làm những gì pickle không, sau đó bạn có thể yêu cầu dill để dưa bằng cách tham khảo với dill.dumps(Foo, byref=True).

Bây giờ, trong trường hợp dưới đây, chúng tôi làm việc với định nghĩa lớp mới và trích xuất nguồn từ đối tượng, sau đó lưu nó vào tệp. Ngoài ra, chúng tôi có thể đổ nguồn vào một tập tin (ở đây tôi sử dụng một tập tin tạm thời) để nó có thể được nhập sau này.

>>> sFoo = dill.source.getsource(Foo) 
>>> print sFoo 
class Foo(object): 
    def bar(self, x): 
    return x*self.z 
    z = -1 

>>> open('myFoo.py', 'w').write(sFoo)  
>>> 
>>> f = dill.temp.dump_source(Foo, dir='.') 
>>> f.name 
'/Users/mmckerns/dev/tmpM1dzYN.py' 
>>> from tmpM1dzYN import Foo as _Foo_ 
>>> h = _Foo_() 
>>> h.bar(2) 
-2 
>>> from myFoo import Foo as _SFoo_ 
>>> _SFoo_.z 
>>> -1 
>>> 

Tôi hy vọng điều đó sẽ hữu ích.

+0

Liên quan đến khối mã đầu tiên của bạn, tôi chạy nó và nó thổi lên chính xác như 'pickle' sẽ: AttributeError: 'Foo' đối tượng không có thuộc tính 'y'. circa line 25. Quá tệ, bởi vì nó có vẻ giống như một phép thuật, và nó sẽ làm cho việc lưu trữ các đối tượng dill-ed trong một cơ sở dữ liệu dễ bảo trì hơn. Vì vậy, có một trường hợp sử dụng rất lớn. Dill 0.2.7.1, thì là các thiết lập mặc định (byref False). Tôi hy vọng đó là lỗi của nhà điều hành, nhưng việc cắt và dán lại chắc chắn trong kỹ năng của tôi. – piccolbo

+0

Lỗi cụ thể đối với ipython. Tiếng thở dài nhẹ nhõm nhưng vẫn khó hiểu ... sẽ điều tra và/hoặc mở một vé – piccolbo

+0

@piccolbo: Lạ lùng. Tôi có thể lặp lại hành vi trong 'ipython' - vì vậy họ phải mucking với điều gì đó bất ngờ. Điều này có vẻ như đó là hành vi mới. Hmm. Tôi đã thấy vé của bạn, cảm ơn. –

Các vấn đề liên quan