如何使具有多个初始化参数的自定义异常类可腌制

新手上路,请多包涵

为什么我下面的自定义异常类不能使用 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 时,不会出现此问题。

谢谢你的帮助。凯尔

编辑:修复我对 super per shx2 的调用 编辑:清理标题/内容

原文由 kylejmcintyre 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 491
2 个回答

使 arg2 可选:

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

基础 Exception 类定义了一个 .__reduce__() 方法 来使扩展(基于 C)类型 picklable 并且该方法只需要 一个 参数(即 .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 Pieters 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果您同时使用这两个参数来构造要传递给父异常类的错误消息,则当前答案会失效。我相信最好的方法是在您的异常中简单地覆盖 __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__ 的更多信息,请 点击此处

原文由 Sean 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题