2009-02-20 19 views
30

bunu gibi genel bir hata iletisiyle başarısız olur salamura edilemez bazı özelliklere sahiptir nesneyi turşu zaman:Hangi nesne özellik turşusunun başarısız olduğunu nasıl anlayabilirim?

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

duruma neden olan nitelik anlatmak için herhangi bir yolu var mı? Python 2.5.2 kullanıyorum. Prensip olarak sorunun temel sebebini (örneğin yukarıdaki örnekte bir örnekleme yöntemine sahip) anladığım halde, 'un'u tam olarak tespit etmek çok zor olabilir. Benim durumumda özel bir __getstate__ yöntemini zaten tanımladım, ancak kritik bir özniteliği unuttum. Bu iç içe geçmiş nesnelerin karmaşık bir yapısında gerçekleşti, bu yüzden kötü özniteliği tanımlamak bana biraz zaman aldı.

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 

Maalesef nitelik test_meth soruna neden dair hiçbir ipucu yoktur:

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) 

Bu çıkış ise: istenen gibi

, burada basit bir örnek kasıtlı turşu vardı başarısız olduğunu.

+0

belki başarısız özelliğinin küçük örnek verebilirim:

Bu konuda unpicklable öğeleri yakalamakta dill.detect kullanımını görüyor musunuz? ya da en azından turşu modülünde nerede başarısız olduğunu görmek için biraz daha fazla traceback gösterilsin mi? – MrTopf

+0

oh ve hangi Python sürümünü kullanıyorsunuz? – MrTopf

+0

@MrTopf: – nikow

cevap

14

Daha fazla yardımcı hata iletisi eklememek için Python'a karşı bir hata yapabilirsiniz. Bu arada, _reduce_ex() işlevini copy_reg.py'da değiştirin.

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

Çıktı:

Seninle aynı problem vardı, ama benim sınıfları (benzer nesnelerin yani büyük bir ağacı) biraz daha karmaşık bu yüzden baskı kadar ki yardımcı olmadı
<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

neden baskı yerine hata mesajına "kendini" koyma? – MrTopf

+1

Bunun örnekte "TypeError" istisnasını kapsadığına inanıyorum, ancak orijinal "PicklingError" istisnası ele alınmıyor. – cmcginty

+0

TypeError, PicklingError'a neden oluyor. Bir keresinde instancemethod nesnelerini (veya başka herhangi bir diğer seçim dışı nesneyi) çalmaya çalışmayı bıraktığınızda her şey çalışmalıdır. – joeforker

8

Bir yardımcı işlevi bir araya getirdim. Bu tam değildir ve sadece dekapaj protokolü 2: ile kullanım için tasarlanmıştır Bu yüzden benim sorunlarımı bulmak için yeterliydi. Her şeyi kapsayacak şekilde genişletmek isterseniz, protokol http://www.python.org/dev/peps/pep-0307/'da açıklanmıştır. Bu yayını düzenlenebilir hale getirdim, böylece herkes kodu güncelleştirebilir.

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 

K Bu attibute K._gen picklable anlamına gelir ve aynı K._base._gens için de geçerlidir

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

turşu etmez amacı, kullanım örneği .

+0

Teşekkürler, yardımcı olur. Ve bence __getstate __() 'karşılık gelen Sınıfta tanımlanmalıdır. –

3

Sana Pickler alt sınıf ve blok dışında bir try Pickler.save() yöntemini kaydırmak eğer dill kullanırsanız

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

Sonra öylesine

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

Bu sadece bir hata ayıklayıcıyı başlatmıyor mu? Soruna bakmak için sadece Eclipse PyDev Debugger'ı kullanmak gibi bir fark var mıdır? – nikow

+0

PyDev hata ayıklayıcısını istisna başlatır ve doğru yürütme düzeyine koyarsanız, aynıdır. Ben bir IDE kullanmıyorum. –

+0

Özellikle zor-bulunacak bir Pickle hatası bulmak için bunu kullandım. Ancak, istisna dışı maddeye sahip olmaktan ziyade hata ayıklayıcısını başlatırdım, sadece bunu yazdırdım ve istisnayı kaldırdım. Daha sonra, MyPickler (output) .dump (obj) komutunu çalıştırarak, çıkarılmamış nesnenin tam olarak iç içe geçmiş yapılarımın tam olarak nerede olduğuyla ilgili iyi bir geri bildirim benzeri bir rapor oluşturdu. Ne gün ama. – partofthething

2

gibi diyoruz bulduk senin örnek

>>> 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.' 

yüzden bir şey t bulmak zorunda ... turşu başarısız değil dill numaralı hat turu alamıyor ...Hata mesajı iyi değilse
>>> 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 
>>> 

, ben üst düzey bir nesne içeren unpicklable neler nesneleri görmek için dill.detect kullanabilirsiniz. varsa belki de kullanmak gerekir, ancak
>>> 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

, mevcut olan __getstate__ yöntem dayanmaz. Pikle yapmayan şeyi oluşturmak için kullanılan tüm nesne bağımlılıklarının resmini almak için objgraph'u da kullanabilirsiniz. Yukarıdaki bilgilerin temelinde sorunun kökeninin ne olduğunu belirlemenize yardımcı olabilir. https://github.com/uqfoundation/dill/issues/58

İlgili konular