2009-02-20 42 views
30

आप एक वस्तु कुछ विशेषताओं जो इसे जैसा कोई सामान्य त्रुटि संदेश के साथ असफल हो जायेगी मसालेदार नहीं किया जा सकता है कि अचार जब:किस ऑब्जेक्ट विशेषता पिक विफल रहता है?

PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed 

वहाँ किसी भी तरह से बताने के लिए जो गुण का अपवाद उत्पन्न है? मैं पाइथन 2.5.2 का उपयोग कर रहा हूँ।

भले ही मैं सिद्धांत में समझता हूं कि समस्या का मूल कारण (उदाहरण के लिए उपर्युक्त उदाहरण में एक उदाहरण विधि है) यह अभी भी पर बहुत मुश्किल हो सकता है, इसे ठीक से पर इंगित करें। मेरे मामले में मैंने पहले ही एक कस्टम __getstate__ विधि परिभाषित की है, लेकिन एक महत्वपूर्ण विशेषता के बारे में भूल गया। यह नेस्टेड ऑब्जेक्ट्स की एक जटिल संरचना में हुआ, इसलिए मुझे खराब विशेषता की पहचान करने में थोड़ी देर लग गई।

now with instancemethod... 
Traceback (most recent call last): 
    File "/home/wilbert/develop/workspace/Playground/src/misc/picklefail.py", line 15, in <module> 
    pickle.dumps(test) 
    File "/home/wilbert/lib/python2.5/copy_reg.py", line 69, in _reduce_ex 
    raise TypeError, "can't pickle %s objects" % base.__name__ 
TypeError: can't pickle instancemethod objects 

दुर्भाग्य से वहाँ कोई संकेत है कि विशेषता test_meth समस्या का कारण बनता है:

import cPickle as pickle 
import new 

class Test(object): 
    pass 

def test_func(self): 
    pass 

test = Test() 
pickle.dumps(test) 
print "now with instancemethod..." 
test.test_meth = new.instancemethod(test_func, test) 
pickle.dumps(test) 

यह आउटपुट है:

के रूप में अनुरोध किया है, यहाँ एक सरल उदाहरण जानबूझकर अचार थे विफल रहता है।

+0

आप शायद एक असफल विशेषता का एक छोटा सा उदाहरण दे सकते हैं:

इस मुद्दे में unpicklable आइटम पर नज़र रखने में dill.detect उपयोग देखते हैं? या कम से कम ट्रेसबैक दिखाएं कि यह देखने के लिए कि अचार मॉड्यूल में यह विफल रहता है? – MrTopf

+0

ओह, और आप किस पायथन संस्करण का उपयोग कर रहे हैं? – MrTopf

+0

@MrTopf: जानकारी – nikow

उत्तर

14

आप पाइथन के खिलाफ एक बग फाइल कर सकते हैं जिसमें अधिक उपयोगी त्रुटि संदेश शामिल नहीं हैं। इस बीच, copy_reg.py में _reduce_ex() फ़ंक्शन को संशोधित करें।

if base is self.__class__: 
    print self # new 
    raise TypeError, "can't pickle %s objects" % base.__name__ 

आउटपुट:

<bound method ?.test_func of <__main__.Test object at 0xb7f4230c>> 
Traceback (most recent call last): 
    File "nopickle.py", line 14, in ? 
    pickle.dumps(test) 
    File "/usr/lib/python2.4/copy_reg.py", line 69, in _reduce_ex 
    raise TypeError, "can't pickle %s objects" % base.__name__ 
TypeError: can't pickle instancemethod objects 
+3

प्रिंट के बजाय त्रुटि संदेश में "स्वयं" क्यों नहीं डालना? – MrTopf

+1

मेरा मानना ​​है कि इसमें उदाहरण में "TypeError" अपवाद शामिल है, हालांकि मूल "PicklingError" अपवाद को संबोधित नहीं किया गया है। – cmcginty

+0

टाइप एरर पिकलिंग एरर का कारण बनता है। एक बार जब आप examplemethod ऑब्जेक्ट्स (या किसी अन्य गैर-अस्थिर वस्तु) को चुनने की कोशिश करना बंद कर देते हैं तो सब कुछ काम करना चाहिए। – joeforker

8

मैं आप के रूप में एक ही समस्या थी, लेकिन मेरी कक्षाओं में थोड़ा और अधिक जटिल थे (यानी समान वस्तुओं की एक बड़ी पेड़) तो मुद्रण इतना मदद नहीं की मैंने एक सहायक समारोह को एक साथ हैक किया। यह पूर्ण नहीं है और केवल पिकलिंग प्रोटोकॉल 2: के साथ उपयोग के लिए है, यह पर्याप्त था इसलिए मैं अपनी समस्याओं का पता लगा सकता था। यदि आप इसे सब कुछ कवर करने के लिए विस्तारित करना चाहते हैं, तो प्रोटोकॉल का वर्णन http://www.python.org/dev/peps/pep-0307/ पर किया गया है, मैंने इस पोस्ट को संपादन योग्य बना दिया है ताकि सभी कोड अपडेट कर सकें।

import pickle 
def get_pickling_errors(obj,seen=None): 
    if seen == None: 
     seen = [] 
    try: 
     state = obj.__getstate__() 
    except AttributeError: 
     return 
    if state == None: 
     return 
    if isinstance(state,tuple): 
     if not isinstance(state[0],dict): 
      state=state[1] 
     else: 
      state=state[0].update(state[1]) 
    result = {}  
    for i in state: 
     try: 
      pickle.dumps(state[i],protocol=2) 
     except pickle.PicklingError: 
      if not state[i] in seen: 
       seen.append(state[i]) 
       result[i]=get_pickling_errors(state[i],seen) 
    return result 

उपयोग का एक उदाहरण है, जहां कश्मीर उद्देश्य यह है कि अचार नहीं है

>>> get_pickling_errors(K) 
{'_gen': {}, '_base': {'_gens': None}} 

इसका मतलब है कि attibute K._gen picklable नहीं है और एक ही K._base._gens के लिए चला जाता है ।

+0

धन्यवाद, यह मदद करता है। और मुझे लगता है कि '__getstate __()' को इसी वर्ग में परिभाषित किया जाना चाहिए। –

3

मैं ने पाया है कि यदि आप पिकलर उपवर्ग और एक कोशिश में Pickler.save() विधि लपेट, ब्लॉक को छोड़कर

import pickle 
class MyPickler (pickle.Pickler): 
    def save(self, obj): 
     try: 
      pickle.Pickler.save(self, obj) 
     except Exception, e: 
      import pdb;pdb.set_trace() 

तब तो

import StringIO 
output = StringIO.StringIO() 
MyPickler(output).dump(thingee) 
+0

क्या यह सिर्फ डीबगर शुरू नहीं कर रहा है? क्या कोई फर्क पड़ता है, उदाहरण के लिए, समस्या को देखने के लिए केवल ग्रहण पायडेव डीबगर का उपयोग करना? – nikow

+0

यदि पीईडीवी डीबगर अपवाद पर शुरू होगा और आपको निष्पादन के सही स्तर पर रखेगा, तो यह वही है। हालांकि मैं एक आईडीई का उपयोग नहीं करता हूं। –

+0

मैंने इसे विशेष रूप से कठिन खोजने के लिए अचार की खोज करने के लिए उपयोग किया। लेकिन छोड़कर खंड को डीबगर शुरू करने के बजाय, मैंने अभी इसे ओबीजे प्रिंट किया था और अपवाद बढ़ाया था। फिर, MyPickler (आउटपुट) .dump (obj) चलाकर परिणामस्वरूप एक अच्छी ट्रेसबैक जैसी रिपोर्ट हुई जहां बिल्कुल अप्रचलित वस्तु मेरे गहरे घोंसले वाले संरचनाओं में थी। क्या दिन है। – partofthething

2

की तरह इसे कहते आप dill का उपयोग करते हैं , आपका उदाहरण अचार में विफल नहीं होता है ...

>>> import dill 
>>> import new 
>>> 
>>> class Test(object): 
...  pass 
... 
>>> def test_func(self): 
...  pass 
... 
>>> test = Test() 
>>> dill.dumps(test) 
'\x80\x02cdill.dill\n_create_type\nq\x00(cdill.dill\n_load_type\nq\x01U\x08TypeTypeq\x02\x85q\x03Rq\x04U\x04Testq\x05h\x01U\nObjectTypeq\x06\x85q\x07Rq\x08\x85q\t}q\n(U\r__slotnames__q\x0b]q\x0cU\n__module__q\rU\x08__main__q\x0eU\x07__doc__q\x0fNutq\x10Rq\x11)\x81q\x12}q\x13b.' 
>>> test.test_meth = new.instancemethod(test_func, test) 
>>> dill.dumps(test) 
'\x80\x02cdill.dill\n_create_type\nq\x00(cdill.dill\n_load_type\nq\x01U\x08TypeTypeq\x02\x85q\x03Rq\x04U\x04Testq\x05h\x01U\nObjectTypeq\x06\x85q\x07Rq\x08\x85q\t}q\n(U\r__slotnames__q\x0b]q\x0cU\n__module__q\rU\x08__main__q\x0eU\x07__doc__q\x0fNutq\x10Rq\x11)\x81q\x12}q\x13U\ttest_methq\x14h\x01U\nMethodTypeq\x15\x85q\x16Rq\x17cdill.dill\n_create_function\nq\x18(cdill.dill\n_unmarshal\nq\x19Ubc\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00C\x00\x00\x00s\x04\x00\x00\x00d\x00\x00S(\x01\x00\x00\x00N(\x00\x00\x00\x00(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\t\x00\x00\x00test_func\x01\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x1a\x85q\x1bRq\x1cc__builtin__\n__main__\nU\ttest_funcq\x1dNN}q\x1etq\x1fRq h\x12N\x87q!Rq"sb.' 

तो हमें कुछ टी ढूंढना है टोपी dill अचार नहीं कर सकता ...

>>> class Unpicklable(object): 
... def breakme(self): 
...  self.x = iter(set()) 
... 
>>> u = Unpicklable() 
>>> dill.dumps(u) 
'\x80\x02cdill.dill\n_create_type\nq\x00(cdill.dill\n_load_type\nq\x01U\x08TypeTypeq\x02\x85q\x03Rq\x04U\x0bUnpicklableq\x05h\x01U\nObjectTypeq\x06\x85q\x07Rq\x08\x85q\t}q\n(U\r__slotnames__q\x0b]q\x0cU\n__module__q\rU\x08__main__q\x0eU\x07breakmeq\x0fcdill.dill\n_create_function\nq\x10(cdill.dill\n_unmarshal\nq\x11U\xafc\x01\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s"\x00\x00\x00d\x01\x00d\x00\x00l\x00\x00}\x01\x00t\x01\x00t\x02\x00\x83\x00\x00\x83\x01\x00|\x00\x00_\x03\x00d\x00\x00S(\x02\x00\x00\x00Ni\xff\xff\xff\xff(\x04\x00\x00\x00t\t\x00\x00\x00itertoolst\x04\x00\x00\x00itert\x03\x00\x00\x00sett\x01\x00\x00\x00x(\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\x07\x00\x00\x00breakme\x02\x00\x00\x00s\x04\x00\x00\x00\x00\x01\x0c\x01q\x12\x85q\x13Rq\x14c__builtin__\n__main__\nh\x0fNN}q\x15tq\x16Rq\x17U\x07__doc__q\x18Nutq\x19Rq\x1a)\x81q\x1b}q\x1cb.' 
>>> u.breakme() 
>>> dill.dumps(u) 
Traceback (most recent call last): 
…(snip)… 
pickle.PicklingError: Can't pickle <type 'setiterator'>: it's not found as __builtin__.setiterator 
>>> 

तो त्रुटि संदेश अच्छा नहीं था, मैं dill.detect का उपयोग करके देखें कि कौन क्या unpicklable वस्तुओं उच्च-स्तरीय वस्तु शामिल हो सकता है।

>>> dill.detect.badobjects(u, depth=1) 
{'__hash__': <method-wrapper '__hash__' of Unpicklable object at 0x10a37b350>, '__setattr__': <method-wrapper '__setattr__' of Unpicklable object at 0x10a37b350>, '__reduce_ex__': <built-in method __reduce_ex__ of Unpicklable object at 0x10a37b350>, '__reduce__': <built-in method __reduce__ of Unpicklable object at 0x10a37b350>, '__str__': <method-wrapper '__str__' of Unpicklable object at 0x10a37b350>, '__format__': <built-in method __format__ of Unpicklable object at 0x10a37b350>, '__getattribute__': <method-wrapper '__getattribute__' of Unpicklable object at 0x10a37b350>, '__delattr__': <method-wrapper '__delattr__' of Unpicklable object at 0x10a37b350>, 'breakme': <bound method Unpicklable.breakme of <__main__.Unpicklable object at 0x10a37b350>>, '__repr__': <method-wrapper '__repr__' of Unpicklable object at 0x10a37b350>, '__dict__': {'x': <setiterator object at 0x10a370820>}, 'x': <setiterator object at 0x10a370820>, '__sizeof__': <built-in method __sizeof__ of Unpicklable object at 0x10a37b350>, '__init__': <method-wrapper '__init__' of Unpicklable object at 0x10a37b350>} 
>>> dill.detect.badtypes(u, depth=1) 
{'__hash__': <type 'method-wrapper'>, '__setattr__': <type 'method-wrapper'>, '__reduce_ex__': <type 'builtin_function_or_method'>, '__reduce__': <type 'builtin_function_or_method'>, '__str__': <type 'method-wrapper'>, '__format__': <type 'builtin_function_or_method'>, '__getattribute__': <type 'method-wrapper'>, '__delattr__': <type 'method-wrapper'>, 'breakme': <type 'instancemethod'>, '__repr__': <type 'method-wrapper'>, '__dict__': <type 'dict'>, 'x': <type 'setiterator'>, '__sizeof__': <type 'builtin_function_or_method'>, '__init__': <type 'method-wrapper'>} 
>>> set(dill.detect.badtypes(u, depth=1).values()) 
set([<type 'dict'>, <type 'method-wrapper'>, <type 'instancemethod'>, <type 'setiterator'>, <type 'builtin_function_or_method'>]) 

dill, __getstate__ विधि मौजूद होने पर निर्भर नहीं करता है, हालांकि शायद यह यह उपयोग करना चाहिए यदि वह मौजूद है। आप ऑब्जेक्ट निर्भरताओं की एक तस्वीर प्राप्त करने के लिए objgraph का उपयोग भी कर सकते हैं जिसका उपयोग ऐसी चीज बनाने के लिए किया जाता है जो अचार नहीं करता है। यह उपरोक्त जानकारी के आधार पर समस्या की जड़ क्या है, यह हल करने में आपकी सहायता कर सकता है। https://github.com/uqfoundation/dill/issues/58

संबंधित मुद्दे