【问题标题】:Why is my custom exception unpickle failing为什么我的自定义异常 unpickle 失败
【发布时间】:2017-01-20 18:19:18
【问题描述】:
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)

我已经进行了一些谷歌搜索,但很难找到一个很好的答案来解释为什么会发生这种情况,并且并不急于开始学习泡菜序列化格式以逐步完成这个:-/

编辑: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'

【问题讨论】:

  • 在我看来这是因为 Exception 类覆盖了 __setstate__?
  • 只是一个注释,试图为您指明一个有用的方向:显然,在 unpickling 时,系统尝试仅使用 2 个参数调用 init。在 Java 环境中,通常要求有一个默认构造函数,该构造函数将通过反射调用,所有其他字段都通过属性设置器方法设置。要么您需要采用这种方法:将您的 init 更改为在没有其他参数的情况下工作,并在 init 完成后让 unpickling 设置它们,或者您可以找到一种方法pickle 告诉它在 unpickling 时需要提供给 init 的附加参数。
  • 您可以进一步简化您的最小示例,因为ABError 的酸洗和解酸会导致相同的错误。
  • 谢谢 - 我已经提出了一个更小的版本stackoverflow.com/questions/41808912/…

标签: python python-2.7 python-3.x


【解决方案1】:

我正在回答一个与此相关的不同问题,它们是相同的。 reduce 将返回如何重新创建对象,它基于 self.args 中的内容。由于您没有将所有参数传递给 Exception 它会中断。如果您需要能够访问自定义字段而无需为 a 执行 e.args[0] 为 b 执行 e.args[1] 等,只需创建属性。 请注意,扩展类仍然调用异常 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-01
    • 1970-01-01
    • 2012-12-04
    • 2020-02-20
    • 2021-10-05
    • 2012-07-09
    • 1970-01-01
    • 2016-09-19
    相关资源
    最近更新 更多