python / python/cpython

Exception that calls `super().__init__` breaks `copy.copy`

未关闭
#125,782 7 条评论 1 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

3.12 3.13 3.14 stdlib type-bug
主要语言
Python
星标
77.2k
派生
35.9k
PR 合并指标
PR 指标待抓取

描述

Bug report

Bug description:

For some reason calling Exception.__init__ breaks copy.copys ability to detect args. The following code

import copy

class MyException(Exception):
    def __init__(self, x):
        super().__init__()
        self.x = x

my_exc = MyException(5)
copy.copy(my_exc)

gives

Traceback (most recent call last):
  File "./foo.py", line 9, in <module>
    copy.copy(my_exc)
  File "/usr/lib/python3.12/copy.py", line 97, in copy
    return _reconstruct(x, None, *rv)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/copy.py", line 253, in _reconstruct
    y = func(*args)
        ^^^^^^^^^^^
TypeError: MyException.__init__() missing 1 required positional argument: 'x'

Removing the super().__init__() line makes everything work as expected, but given that it's generally seen as good practice to call super().__init__() in child classes, and you may be working with a more complex class structure, this seems like pretty bad behavior.
I haven't dug deep enough into copy.copy or BaseException.__init__ to decide which one deserves the blame.

For the reason why I want to copy exceptions, see https://github.com/python-trio/flake8-async/issues/298

CPython versions tested on:

3.9, 3.10, 3.11, 3.12, 3.13, 3.14

Operating systems tested on:

Linux

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

使用 copy.copy 重现该示例,并结合 BaseException.init 检查 /usr/lib/python3.12/copy.py 中的行为。确定初始化器调用 super().init() 的 Exception 的预期复制行为,然后添加一个回归测试,表明复制能够保留所需的构造函数状态且不会引发 TypeError。

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
backend
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。