我写了一个关于Python生成器的测试程序。但我犯了一个意想不到的错误。我不知道该怎么解释。让我给你看看密码:
def countdown(n):
logging.debug("Counting down")
while n > 0:
try:
yield n
except GeneratorExit:
logging.error("GeneratorExit")
n -= 1
if __name__ == '__main__':
c = countdown(10)
logging.debug("value: %d", c.next())
我认为它应该运行没有任何问题。但结果是:
# ./test.py
[2015/06/16 04:10:49] DEBUG - Counting down
[2015/06/16 04:10:49] DEBUG - value: 10
[2015/06/16 04:10:49] ERROR - GeneratorExit
Exception RuntimeError: 'generator ignored GeneratorExit' in <generator object countdown at 0x7f9934407640> ignored
为什么最后一行有错误。我不知道为什么我触发了GeneratorExit异常。除了发电机我还有什么遗漏吗?我还将代码输入到交互式python shell中,一切正常。怎么会这样?
当生成器对象在程序结束时被垃圾收集时,将调用其
close()
方法,这将在生成器中引发GeneratorExit
异常。通常,这不会被捕获并导致发电机退出。由于捕捉到异常并继续产生另一个值,这将导致
RuntimeError
。如果捕捉到GeneratorExit
异常,则需要重新引发该异常,或者退出该函数而不产生任何其他异常。可能是因为您的屈服值n在try块中,try块总是返回新的n引用,这使得最后的n值被自动垃圾收集。它也是PEP 342中的状态:
由于生成器中的close方法相当于抛出GeneratorExit并被您的异常捕获,因此将执行
logging.error('GeneratorExit')
表达式。“RunTimeError”是由于生成器产生下一个值n(9)而引发的,它是python文档中的状态https://docs.python.org/3.6/reference/expressions.html#generator-iterator-methods:
可能是这样的代码:
然后在你的终端:
将导致:
很抱歉我的英语不好或我的建议不够清楚,谢谢
假设您有以下生成器:
你只要
next
一次就把它扔掉:生成器的控制流从不离开
with
块,因此文件不会被关闭。为了防止这种情况,当垃圾收集生成器时,Python调用其close
方法,该方法在生成器最后一次运行时引发GeneratorExit
异常。此异常旨在触发任何没有机会运行的finally
块或上下文管理器__exit__
。当您捕获
GeneratorExit
并继续运行时,Python会看到生成器没有正确退出。因为这可能表示资源没有正确释放,所以Python将其报告为运行时错误。相关问题 更多 >
编程相关推荐