2013-04-26 19 views
10

Özel özel durum sınıfımın altında neden turşu modülünü kullanarak seri hale getirilmiyor/dizisi kaldırılamıyor?Birden çok init args seçilebilen özel bir özel durum sınıfı nasıl yapılır

Traceback (most recent call last): 
File "test.py", line 13, in <module> 
    obj = pickle.loads(str) 
File "/usr/lib/python2.7/pickle.py", line 1382, in loads 
    return Unpickler(file).load() 
File "/usr/lib/python2.7/pickle.py", line 858, in load 
    dispatch[key](self) 
File "/usr/lib/python2.7/pickle.py", line 1133, in load_reduce 
    value = func(*args) 
TypeError: __init__() takes exactly 3 arguments (2 given) 

Bu sorun bir sınıf turşu dostu hale nasıl benim tarafında bilgi eksikliğinden kaynaklanıyor eminim:

import pickle 

class MyException(Exception): 
    def __init__(self, arg1, arg2): 
     self.arg1 = arg1 
     self.arg2 = arg2 

     super(MyException, self).__init__(arg1) 

e = MyException("foo", "bar") 

str = pickle.dumps(e) 
obj = pickle.loads(str) 

Bu kod aşağıdaki hatayı atar. İlginçtir, sınıfım Özel Durum'u genişletmediğinde bu sorun oluşmaz.

Yardımlarınız için teşekkür ederiz. Kyle

DÜZENLEME: shx2 başına super EDIT çağrıma Tespit: Başlık temizleniyor/içerik

cevap

7

arg2 isteğe bağlı yap:

class MyException(Exception): 
    def __init__(self, arg1, arg2=None): 
     self.arg1 = arg1 
     self.arg2 = arg2 
     super(MyException, self).__init__(arg1) 

Exception sınıf uzantısını yapmak için bir .__reduce__() method tanımlar taban (C-tabanlı) seçilebilir tip ve bu yöntem sadece bir argümanını (.args) bekliyor; BaseException_reduce() function in the C source'a bakın.

En kolay çalışma, isteğe bağlı ek argümanlar yapmaktır. Ayrıca herhangi bir ek nesne içeren __reduce__ yöntem .args ve .message ötesine niteliklerini ve örnekleri düzgün yeniden yaratılır:

>>> e = MyException('foo', 'bar') 
>>> e.__reduce__() 
(<class '__main__.MyException'>, ('foo',), {'arg1': 'foo', 'arg2': 'bar'}) 
>>> pickle.loads(pickle.dumps(e)) 
MyException('foo',) 
>>> e2 = pickle.loads(pickle.dumps(e)) 
>>> e2.arg1 
'foo' 
>>> e2.arg2 
'bar' 
7

Ben Martijn yanıtını gibi ama daha iyi bir yolu Exception temel sınıf tüm argümanları geçmek olduğunu düşünüyorum :

class MyException(Exception): 
    def __init__(self, arg1, arg2): 
     super(MyException, self).__init__(arg1, arg2)   
     self.arg1 = arg1 
     self.arg2 = arg2 

temel Exception sınıfının __reduce__ yöntem, tüm bağımsız değişken içerir. İsteğe bağlı tüm bağımsız değişkenleri yapmamakla, istisnanın doğru bir şekilde oluşturulduğundan emin olabilirsiniz.

4

Geçerli istisnalar, üst Özel durum sınıfına geçmek için bir hata iletisi oluşturmak için her iki bağımsız değişken kullanıyorsanız de bozulur. En iyi yolun istisnanızda __reduce__ yöntemini geçersiz kılmanın en iyi yol olduğuna inanıyorum. __reduce__ yöntemi, iki öğeli bir tuple döndürmelidir. Tuple'daki ilk öğe senin sınıfın. İkinci öğe, sınıfınızın __init__ yöntemine geçmek için argümanları içeren bir tupledır.

import pickle 

class MyException(Exception): 
    def __init__(self, arg1, arg2): 
     self.arg1 = arg1 
     self.arg2 = arg2 

     super(MyException, self).__init__('arg1: {}, arg2: {}'.format(arg1, arg2)) 

    def __reduce__(self): 
     return (MyException, (self.arg1, self.arg2)) 


original = MyException('foo', 'bar') 
print repr(original) 
print original.arg1 
print original.arg2 

reconstituted = pickle.loads(pickle.dumps(original)) 
print repr(reconstituted) 
print reconstituted.arg1 
print reconstituted.arg2 

diğer bilgiler hakkında __reduce__here.