How to make a custom exception class with multiple init args pickleable
为什么我下面的自定义异常类不能使用pickle模块正确地序列化/反序列化?
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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) |
此代码抛出以下错误:
1 2 3 4 5 6 7 8 9 10 | 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编辑:清理标题/内容
如果您同时使用两个参数来构造传递给父异常类的错误消息,则当前答案将被分解。我认为最好的方法是在异常中简单地覆盖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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 |
更多关于
1 2 3 4 5 | class MyException(Exception): def __init__(self, arg1, arg2=None): self.arg1 = arg1 self.arg2 = arg2 super(MyException, self).__init__(arg1) |
基
最简单的解决方法是让额外的参数可选。
1 2 3 4 5 6 7 8 9 10 | >>> 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的回答,但是我认为更好的方法是将所有的参数传递给
1 2 3 4 5 | class MyException(Exception): def __init__(self, arg1, arg2): super(MyException, self).__init__(arg1, arg2) self.arg1 = arg1 self.arg2 = arg2 |
基本的