什么类型的消息“被忽略的例外”是?

时间:2016-06-26 08:18:58

标签: python python-3.x

这是代码:

var holderelement=document.body;
var howmanylinksyouwant=3;
for (var i=0;i<howmanylinksyouwant;i++){
var li=document.createElement("li");
li.onclick=function(){location.href="stackoverflow.com";}
li.style.textAlign="center";
li.innerHTML="<b>ep "+i+"</b>" holderelement.append(li);
}

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

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警告(它看起来不像我们在调用warnings时得到的那样)。

我认为它可以与异常相关联,但我无法用warnings.warn来捕捉它,而msg本身就消失了:

sys.excepthook

我怎样才能听到这个警告?

如何手动创建此类警告?

2 个答案:

答案 0 :(得分:6)

有些人已经注意到,并非每个人都能得到你所描述的行为。例如,您在REPL中无法获得此行为。要在REPL上重现此行为,您必须在末尾添加del gen。这让我们知道警告的来源。警告来自发电机对象的清理功能,发现发电机没有干净地退出。

具体发生的是,当解释器正在尝试清理发生器并释放其资源时,生成器引发了异常。解释器无法传播此异常,因此它会记录此状态并继续。具体来说,正在调用PyErr_WriteUnraisablehere就是如何调用它(我的评论)。

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);
    }

    ...
}

答案 1 :(得分:0)

当我运行你的代码时,我得到:

1
>>>

没有错误(我也在Windows 10上使用Python 3.5.1), 但您可以使用以下代码来确定代码中的错误:

try:
    a = int('a')            # here you can put your code
except Exception as e:
    print(e)                # this prints error message   
    print(type(e).__name__) # this prints name of your error

在这种情况下,你得到这个输出:

invalid literal for int() with base 10: 'a'
ValueError
>>>

所以现在你可以使用:

来捕捉错误
to_convert = 'a'
try:
    a = int(to_convert)           
except ValueError:
    print(to_convert, 'can\'t be converted to string.')

通过查看您的错误消息,我认为您对RuntimeError而不是GeneratorExit存在问题。

希望它有所帮助。

编辑:

正如@interjay在评论中说的那样,当我运行你的代码生成器时,对象并没有被破坏,所以没有错误。

问题是当python破坏生成器对象时,在执行此代码时会调用generator.close()产生错误:

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

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

你得到:

RuntimeError: generator ignored GeneratorExit
>>>

但是当生成器对象被销毁(删除)时,异常被忽略。

要避免此警告,您可以在代码中调用generator.close()然后捕获错误,因此您的代码应如下所示:

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

gen = g()
print(gen.__next__())
try:
    gen.close()
except RuntimeError:
    pass