内部产量与块保持开放postgres连接

BHC*_*BHC 2 python psycopg2 generator

yield从下面的发生器进入时,postgres连接是否保持活动状态,或者是否yield需要减少缩进,以便在每个连接器上建立新的连接next()

def getData(start, end):
    with psycopg2.connect("dbname='test' user='user' host='localhost' password='password'") as conn:
        time = start
        while time<end:
            with conn.cursor() as cur:
                cur.execute(query.format(start, time))
                data = cur.fetchall()
            time += one_week
            yield data
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 5

是的,上下文管理器保持活动状态.yield 暂停功能,没有任何退出.

yield不会改变函数内部的执行顺序.该函数仅仅是"暂停",在yield表达式执行时冻结并生成一个值.当稍后恢复生成器时(通过调用__next__迭代器),该函数将再次在该点继续.一个with说法__exit__,当发电机暂停方法不能被调用,所以上下文管理器无法退出直到发电机恢复,反正.

如果您使用@contextmanager装饰器创建一个简单的上下文管理(本身依赖于生成器来实现!),您可以看到这种情况发生:

import sys
from contextlib import contextmanager

@contextmanager
def loud_contextmanager():
    print("Context entered!")
    try:
        yield "value to bind the 'as' target to"
    finally:
        exc_info = sys.exc_info()
        if exc_info:
            print("Context exited with an exception!", exc_info)
        else:
            print("Context exited!")

def generator_stages():
    yield "First yield, outside of a context manage"
    with loud_contextmanager() as cm_as_value:
        yield f"Inside of the with block, received {cm_as_value}"
    yield "Outside of with block, last yield"
Run Code Online (Sandbox Code Playgroud)

当你从生成器中提取值进行打印时,你会看到:

>>> gen = generator_stages()
>>> print(next(gen))
First yield, outside of a context manage
>>> print(next(gen))
Context entered!
Inside of the with block, received value to bind the 'as' target to
>>> print(next(gen))
Context exited with an exception! (None, None, None)
Outside of with block, last yield
>>> next(gen, "generator was done")
'generator was done'
Run Code Online (Sandbox Code Playgroud)

请注意,在我们检索第3个值之前不会退出上下文!在第二次next()调用之后,代码在with块内部的某个点暂停,并且只有在取消暂停时才能退出上下文,并且可以运行finallyloud_contextmanager()函数的套件.