如何使用多个初始化参数创建自定义异常类pickleable

为什么我的自定义Exception类不能使用pickle模块正确序列化/反序列化?

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)

此代码引发以下错误:

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)

我确信这个问题是由于我缺乏关于如何使课堂友好的知识。 有趣的是,当我的类没有扩展Exception时,这个问题不会发生。

谢谢你的帮助。 凯尔

编辑:修复我的电话超级每shx2编辑:清理标题/内容


使arg2可选:

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

基类Exception类定义了一个.__reduce__()方法来使扩展(基于C的)类型可选,并且该方法只需要一个参数(即.args ); 请参阅C源代码中的BaseException_reduce()函数。

最简单的解决方法是使额外的参数可选。 __reduce__方法还包含.args.message之外的任何其他对象属性,并且您的实例可以正确地重新创建:

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

我喜欢Martijn的回答,但我认为更好的方法是将所有参数传递给Exception基类:

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

基本Exception类的__reduce__方法将包含所有的参数。 通过不使所有额外参数可选,您可以确保异常构造正确。


如果您使用两个参数来构造传递给父Exception类的错误消息,则当前的答案会失效。 我相信最好的方法是在你的异常中简单地覆盖__reduce__方法。 __reduce__方法应该返回一个两元组元组。 元组中的第一项是你的类。 第二项是包含传递给你的类的__init__方法的参数的元组。

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

有关__reduce__更多信息, __reduce__点击此处。

链接地址: http://www.djcxy.com/p/20855.html

上一篇: How to make a custom exception class with multiple init args pickleable

下一篇: Use of final class in Java