2009-08-28 36 views
6

(Bạn có thể đọc this câu hỏi đối với một số nền)tẩy Gracefully-hạ bằng Python

Tôi muốn có một cách duyên dáng-hạ để dưa đối tượng trong Python.

Khi chọn một đối tượng, hãy gọi nó là đối tượng chính, đôi khi Pickler đặt ra một ngoại lệ vì nó không thể chọn một đối tượng phụ nhất định của đối tượng chính. Ví dụ: lỗi tôi đã nhận được rất nhiều là "không thể chọn đối tượng mô-đun". Đó là bởi vì tôi đang tham chiếu một mô-đun từ đối tượng chính.

Tôi biết tôi có thể viết một chút gì đó để thay thế mô-đun đó bằng mặt tiền có chứa thuộc tính của mô-đun, nhưng điều đó sẽ có vấn đề riêng (1).

Vì vậy, những gì tôi muốn là một chức năng tẩy tự động thay thế các mô-đun (và bất kỳ đối tượng khó chọn nào khác) với mặt tiền chứa các thuộc tính của chúng. Điều đó có thể không tạo ra một chất tẩy rửa hoàn hảo, nhưng trong nhiều trường hợp, nó sẽ là đủ.

Có điều gì giống như thế này không? Có ai có một ý tưởng làm thế nào để tiếp cận này?


(1) Một vấn đề có thể là mô-đun có thể tham chiếu các mô-đun khác từ bên trong nó.

+1

Đậu Java .. Python Pickles .. Tôi muốn điều tiết các nerds đã đưa ra điều này công cụ cutesy –

Trả lời

0

Làm thế nào về sau đây, mà là một wrapper bạn có thể sử dụng để bọc một số mô-đun (có thể là bất kỳ mô-đun) trong một cái gì đó là có thể chọn. Sau đó bạn có thể phân lớp đối tượng Pickler để kiểm tra xem đối tượng đích có phải là một mô-đun hay không, và nếu có, hãy bọc nó. Điều này có đạt được những gì bạn mong muốn không?

class PickleableModuleWrapper(object): 
    def __init__(self, module): 
     # make a copy of the module's namespace in this instance 
     self.__dict__ = dict(module.__dict__) 
     # remove anything that's going to give us trouble during pickling 
     self.remove_unpickleable_attributes() 

    def remove_unpickleable_attributes(self): 
     for name, value in self.__dict__.items(): 
      try: 
       pickle.dumps(value) 
      except Exception: 
       del self.__dict__[name] 

import pickle 
p = pickle.dumps(PickleableModuleWrapper(pickle)) 
wrapped_mod = pickle.loads(p) 
0

Hmmm, cái gì như thế này?

import sys 

attribList = dir(someobject) 
for attrib in attribList: 
    if(type(attrib) == type(sys)): #is a module 
     #put in a facade, either recursively list the module and do the same thing, or just put in something like str('modulename_module') 
    else: 
     #proceed with normal pickle 

Rõ ràng, điều này sẽ đi vào một phần mở rộng của lớp dưa với một phương pháp bãi reimplemented ...

3

Bạn có thể quyết định và thực hiện như thế nào bất kỳ loại trước đó unpicklable được ngâm và unpickled: xem thư viện chuẩn mô-đun copy_reg (được đổi tên thành copyreg bằng Python 3. *).

Về cơ bản, bạn cần cung cấp một hàm, cho một thể hiện kiểu, giảm nó thành một bộ - với cùng một giao thức như phương thức đặc biệt reduce (ngoại trừ việc giảm phương pháp đặc biệt không có đối số) miễn là nó được gọi trực tiếp trên đối tượng, trong khi hàm bạn cung cấp sẽ lấy đối tượng làm đối số duy nhất).

Thông thường, bộ trả về bạn có 2 mục: một cuộc gọi và một bộ đối số để chuyển cho nó. Người gọi phải được đăng ký là "nhà xây dựng an toàn" hoặc tương đương có thuộc tính __safe_for_unpickling__ với giá trị thực. Các mục đó sẽ được chọn, và vào thời gian không được gọi, các cuộc gọi sẽ được gọi với các đối số đã cho và phải trả về đối tượng chưa được đánh dấu. Ví dụ, giả sử rằng bạn muốn chỉ mô-đun dưa theo tên, để giải thích chúng chỉ có nghĩa là nhập lại chúng (ví dụ: giả sử đơn giản là bạn không quan tâm đến các mô-đun được sửa đổi động, gói lồng nhau, v.v., v.v.) mô-đun cấp cao nhất đơn giản).Sau đó:

>>> import sys, pickle, copy_reg 
>>> def savemodule(module): 
... return __import__, (module.__name__,) 
... 
>>> copy_reg.pickle(type(sys), savemodule) 
>>> s = pickle.dumps(sys) 
>>> s 
"c__builtin__\n__import__\np0\n(S'sys'\np1\ntp2\nRp3\n." 
>>> z = pickle.loads(s) 
>>> z 
<module 'sys' (built-in)> 

Tôi đang sử dụng hình thức ASCII old-fashioned của dưa để s, các chuỗi chứa dưa, rất dễ dàng để kiểm tra: nó hướng dẫn Công cụ unpickling gọi được xây dựng trong chức năng nhập khẩu, với string sys là đối số duy nhất của nó. Và z cho thấy rằng điều này thực sự cho chúng ta trở lại mô-đun sys được tích hợp như là kết quả của việc giải nén, như mong muốn.

Bây giờ, bạn sẽ phải làm cho mọi việc phức tạp hơn một chút so với chỉ __import__ (bạn sẽ phải giải quyết và khôi phục thay đổi động, điều hướng vùng tên lồng nhau, v.v.) hãy gọi copy_reg.constructor (chuyển làm đối số cho chức năng của riêng bạn thực hiện công việc này) trước khi bạn copy_reg chức năng tiết kiệm mô-đun trả về chức năng khác của bạn (và, nếu chạy riêng, cũng trước khi bạn bỏ ghim những dưa chua bạn đã thực hiện bằng chức năng đã nói). Nhưng tôi hy vọng những trường hợp đơn giản này sẽ giúp cho thấy rằng thực sự không có gì nhiều với nó, đó là tất cả "thực chất" phức tạp! -)

+0

@ Alex Martelli: Khi tôi sử dụng copy_reg.pickle, phạm vi mà thay đổi này sẽ có liên quan là gì? Tôi muốn mọi người có thể nhập công việc của mình mà không thay đổi bất kỳ giá trị hệ thống nào có thể phá hỏng chương trình của họ. –

+0

'copy_reg' là toàn cầu. Nhưng nếu hiện tại họ không chọn các mô-đun (điều không thể được mặc định của hệ thống), nó không thể "phá hỏng chương trình của họ" để làm cho các mô-đun có thể chọn được. –

+0

@ Alex Martelli: Nhưng nếu chúng chạy vào cùng một vấn đề và xác định mô-đun tẩy theo một cách khác, chúng tôi sẽ gặp sự cố. Tôi tin là lịch sự và không thay đổi trạng thái hệ thống. Tôi tin rằng khi bạn nhập một số mô-đun trong Python, bạn không cần phải lo lắng về việc nó rối tung với các hình cầu của hệ thống của bạn, và điều quan trọng là phải có các công cụ cho phép bạn tránh loại "bất lịch sự" này trong các mô-đun của bạn. –