在上下文管理器中无价值的收益是什么 [英] what does yield without value do in context manager

查看:72
本文介绍了在上下文管理器中无价值的收益是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

import contextlib
import time

@contextlib.contextmanager
def time_print(task_name):
    t = time.time()
    try:
        yield
    finally:
        print task_name, "took", time.time() - t, "seconds."


def doproc():
    x=1+1


with time_print("processes"):
    [doproc() for _ in range(500)]

# processes took 15.236166954 seconds.

使用此装饰器时doproc何时执行?

when does doproc get executed when using this decorator?

推荐答案

yield表达式将控制权返回给使用生成器的对象.此时,生成器暂停,这意味着@contextmanager装饰器知道代码是由 setup 部分完成的.

yield expression returns control to the whatever is using the generator. The generator pauses at this point, which means that the @contextmanager decorator knows that the code is done with the setup part.

换句话说,您要在上下文管理器__enter__阶段中执行的所有操作都必须在yield之前进行.

In other words, everything you want to do in the context manager __enter__ phase has to take place before the yield.

一旦上下文退出(因此with语句下的块完成),就为上下文管理器协议的__exit__部分调用@contextmanager装饰器,它将执行以下两项操作之一:

Once your context exits (so the block under the with statement is done), the @contextmanager decorator is called for the __exit__ part of the context manager protocol and will do one of two things:

  • 如果没有异常,它将恢复您的生成器.因此,生成器在yield行取消暂停,然后进入清理阶段,即

  • If there was no exception, it'll resume your generator. So your generator unpauses at the yield line, and you enter the cleanup phase, the part

如果存在异常,则装饰器使用generator.throw()在生成器中引发该异常.就像yield行导致了该异常.因为您有一个finally子句,它将在生成器由于异常而退出之前执行.

If there was an exception, the decorator uses generator.throw() to raise that exception in the generator. It'll be as if the yield line caused that exception. Because you have a finally clause, it'll be executed before your generator exits because of the exception.

因此,在您的特定示例中,顺序如下:

So, in your specific example the sequence is as follows:

  1. with time_print("processes"):

这将创建上下文管理器并在其上调用__enter__.

This creates the context manager and calls __enter__ on that.

生成器开始执行,t = time.time()运行.

The generator starts execution, t = time.time() is run.

yield表达式会暂停生成器,控制权会回到装饰器.如果有as target部分,这将采用产生的所有内容,并将其返回给with语句.产生None(只有简单的yield表达式).

The yieldexpression pauses the generator, control goes back to the decorator. This takes whatever was yielded and returns that to the with statement, in case there is an as target part. Here None is yielded (there is only a plain yield expression).

[doproc() for _ in range(500)]运行并完成.

上下文管理器__exit__方法正在运行,没有传入任何异常.

The context manager __exit__ method is run, no exception is passed in.

装饰器恢复生成器,从中断处继续.

The decorator resumes the generator, it continues where it left off.

输入finally:块并执行print task_name, "took", time.time() - t, "seconds.".

生成器退出,装饰器__exit__方法退出,全部完成.

The generator exits, the decorator __exit__ method exits, all is done.

这篇关于在上下文管理器中无价值的收益是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆