当前位置:  开发笔记 > 编程语言 > 正文

无法释放异常子类

如何解决《无法释放异常子类》经验,为你挑选了1个好方法。

为什么我的自定义异常解除失败的简化版本。

我正在尝试腌制一个“简单”异常子类。它腌制还可以,但是当腌制时会掉下来:

import pickle

class ABError(Exception):
    def __init__(self, a, b):
        self.a = a
        self.b = b

ab_err = ABError("aaaa", "bbbb")

pickled = pickle.dumps(ab_err)
original = pickle.loads(pickled)  # Fails

错误:

Traceback (most recent call last):
  File "p.py", line 12, in 
    original = pickle.loads(pickled)  # 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 3 arguments (1 given)

较早的注释建议该问题是因为内置Exception类提供了一种__setstate_()方法。但是,我不清楚这是否是预期的行为-这肯定令人惊讶,因为使用Works的子类执行相同的操作object还可以。



1> spectras..:

BaseException类定义的自定义__reduce__在方法exceptions.c,它返回的参数传递到列表中__init__。确切的代码是

if (self->args && self->dict)
    return PyTuple_Pack(3, Py_TYPE(self), self->args, self->dict);
else
    return PyTuple_Pack(2, Py_TYPE(self), self->args);

根据__reduce__文档,

元组的第一项是可调用的调用。在这里,这将是异常类。

第二项是传递给可调用对象的参数的元组。在这里,将是self.args

第三项是将合并为的命令self.__dict__

因此,由此,BaseException.__reduce__可以使给定参数调用异常的构造函数。

您有两个选择:覆盖__reduce__,或者直接或通过让父类来将所需的参数放在self.args中:

import pickle

class ABError(Exception):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        # self.args = (a, b)
        # maybe better, let base class's __init__ do it =>
        super(ABError, self).__init__(a, b)

ab_err = ABError("aaaa", "bbbb")

pickled = pickle.dumps(ab_err)
original = pickle.loads(pickled)  # no longer fails

请注意,最初的问题来自BaseException泡菜处理的幼稚方式。它已在最新的python3版本中修复。例如,您问题的原始代码在python 3.5上运行良好。

推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有