python - 如何在尚未迭代的生成器中捕获 GeneratorExit?

标签 python

例如,

In [33]: def gener():
    ...:   try:
    ...:     print('hi')
    ...:     yield 1
    ...:     print('hi 2')
    ...:     yield 2
    ...:   except:
    ...:     print('Closed: {!r}'.format(sys.exc_info()[1]))
    ...:

In [34]: gener().close()

# ↑ No output!
In [35]: g = gener()

In [36]: next(g)
hi
Out[36]: 1

In [37]: g.close()
Closed: GeneratorExit()

如果您没有进入 Python 中的生成器,是否不可能注意到生成器的 close() 调用?

(在我的实际用例中,生成器的参数之一是返回生成器的函数传递给生成器的资源,包括所有权。即,

def do_it():
    resource = acquire()
    try:
        return a_generator(resource)()  # pass ownership of the resource
    except:
        resource.close()

如果您在第一次迭代之前关闭生成器,并且生成器无法捕获该事实,则资源将被泄漏。)

最佳答案

你不能。如果生成器尚未被 nexted,则主体内的任何 try 子句都不会被输入。 close 将在函数开始时抛出 GeneratorExit,然后才能设置任何异常处理。

您必须更改前提 - 例如,通过引入虚拟 yield 并提前 next 生成器:

def gen_wrapper():
    gen_iter = _gen()
    next(gen_iter)
    return gen_iter

def _gen():
    try:
        yield
        ...
    finally:
        perform_cleanup()

# Generator returned from gen_wrapper will perform cleanup even if closed immediately.

关于python - 如何在尚未迭代的生成器中捕获 GeneratorExit?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45602322/

相关文章:

python - BuildBot - 可以进行动态 repo 结账吗?

python - 使用区分大小写和不区分大小写的混合模式的正则表达式查找文本中使用的人称代词的数量

Python Web Scraper : My script is just printing the first one, 而不是全部?

python - 如何使用字典理解+ if/else 更改字典中的键值?

python - 我们可以用 python 生成器读取 pickle 文件中的数据吗

python - 在 OpenERP 中创建用户的问题

python - 从另一类的一个类调用函数时发生TypeError

python - boto3 ConnectionClosedError python

python - 操作系统错误: [WinError 126] module could not be found

如果 streams=True,Python Requests 模块不处理超时?