下面是代码:

def g():
    try:
        yield 1
        yield 2
        yield 3
    except GeneratorExit:
        yield 4

gen = g()
print(gen.__next__())

如果你运行它,你会看到:

1
Exception ignored in: <generator object g at 0x00000216BB546A98>
RuntimeError: generator ignored GeneratorExit

我知道发生了什么,但我找不到这个警告是什么类型的信息.

看起来不是logging警告(我无法删除它设置日志(log)级别).这也不是warnings警告(它看起来不像我们打warnings.warn时得到的).

我以为它可以与异常关联,但我不能用sys.excepthook捕捉它,而msg本身消失了:

import sys

def hook(exc_type, exc_val, tb):
    print(exc_type, exc_val, tb)  # Nothing prints, while msg disappear

sys.excepthook = hook

我怎样才能抓住这个警告?

如何手动创建此类警告?

推荐答案

正如一些人指出的,并不是每个人都能得到你描述的行为.例如,你在REPL上就不会有这种行为.要在REPL上重现这种行为,必须在末尾添加del gen.这让我们知道警告的来源.警告来自发电机对象的清理功能,该功能已注意到发电机未干净退出.

具体的情况是,当解释器试图清理生成器并释放其资源时,生成器引发了一个异常.解释器无法将此异常传播回来,因此它会记录此状态并继续.具体来说,PyErr_WriteUnraisable是被称为.here就是它的名字(我的 comments ).

void
_PyGen_Finalize(PyObject *self)
{
    ...

    if (gen is a coroutine) {
        // special error detecting logic for coroutines
    }
    else {
        res = gen_close(gen, NULL); // <- raises GeneratorExit
    }

    if (res == NULL) {
        if (PyErr_Occurred()) {
            PyErr_WriteUnraisable(self);
        }
    }
    else {
        Py_DECREF(res);
    }

    ...
}

Python-3.x相关问答推荐

为什么打印语句在Python多处理脚本中执行两次?

从PYTHON中获取单行和多行的Rguar表达式

ValueError at /register/ 视图authenticate.views.register_user 未返回HttpResponse 对象.它返回 None 相反

错误:无法为 pyconcorde 构建轮子,这是安装基于 pyproject.toml 的项目所必需的

Python根据条件从多行读取值

拆分列表的元素并将拆分后的元素包含到列表中

Pytest顺序测试A,然后测试B,然后再测试A

无法提出给定 for 循环的原因 (Python 3.11)

Python 3 - 给定未知数量的类别动态地将字典嵌套到列表中

这种类型提示有什么作用?

pip 找不到最新的软件包版本

SMTP 库 Python3:不太安全的应用程序访问

使用 pandas 进行多类分类的总体准确度

没有可重定向到的 URL.提供一个 url 或在模型上定义一个 get_absolute_url 方法

django.core.exceptions.ImproperlyConfigured

为什么Pandas会在 NaN 上合并?

Python 错误:IndexError:字符串索引超出范围

如何在 Python 中计算两个包含字符串的列表的 Jaccard 相似度?

为现有项目创建virtualenv

尾部斜杠的 FastAPI 重定向返回非 ssl 链接