import pickle
class ABError(Exception):
def __init__(self, a, b):
super(ABError, self).__init__(a)
self.a = a
self.b = b
class ABCDError(ABError):
def __init__(self, a, b, c, d):
super(ABCDError, self).__init__(a, b)
self.c = c
self.d = d
err = ABCDError("aaaaa", "bbbbb", "ccccc", "ddddd")
pickled_err = pickle.dumps(err)
original_err = pickle.loads(pickled_err) # Fails
我得到以下回溯:
Traceback (most recent call last):
File "pickle_pain.py", line 19, in <module>
original_err = pickle.loads(pickled_err) # Fails
File "/usr/lib/python2.7/pickle.py", line 1388, in loads
return Unpickler(file).load()
File "/usr/lib/python2.7/pickle.py", line 864, in load
dispatch[key](self)
File "/usr/lib/python2.7/pickle.py", line 1139, in load_reduce
value = func(*args)
TypeError: __init__() takes exactly 5 arguments (2 given)
我已经做了一些谷歌搜索,但很难找到一个很好的答案来解释为什么会发生这种情况,并且不急于开始学习 pickle 序列化格式以逐步解决这个问题:-/
编辑:行为在 python3 中是相同的,尽管错误消息稍微好一些:
Traceback (most recent call last):
File "pickle_pain.py", line 19, in <module>
original_err = pickle.loads(pickled_err) # Fails
TypeError: __init__() missing 3 required positional arguments: 'b', 'c', and 'd'
最佳答案
我在回答一个与这个问题相关的不同问题,它们有点相同。 reduce 将返回如何重新创建对象,它基于 self.args 中的内容。由于您没有将所有参数传递给 Exception 它会中断。如果您需要能够在不为 a 执行 e.args[0] 和为 b 执行 e.args[1] 等的情况下访问自定义字段,只需创建属性即可。 请注意,Extended 类仍然调用异常 init 而不是 ABError.init。
import pickle
class ABError(Exception):
def __init__(self, a, b):
super(ABError, self).__init__(a, b)
@property
def a(self):
return self.args[0]
@property
def b(self):
return self.args[1]
class ABCDError(ABError):
def __init__(self, a, b, c, d):
super(ABError, self).__init__(a, b, c, d)
@property
def c(self):
return self.args[2]
@property
def d(self):
return self.args[3]
err = ABCDError("aaaaa", "bbbbb", "ccccc", "ddddd")
pickled_err = pickle.dumps(err)
original_err = pickle.loads(pickled_err) # Fails
关于python - 为什么我的自定义异常 unpickle 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41770024/