从下面的生成器进行yield
的连接时,postgres连接是否保持活动状态?还是需要减少yield
的缩进量,以便在每个next()
上都建立一个新的连接? / p>
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
答案 0 :(得分:5)
是的,上下文管理器保持活动状态。 yield
暂停该功能,没有任何退出。
yield
不会改变函数内部的执行顺序。该函数只是“暂停”,冻结在yield
表达式已执行并产生值的位置。当稍后恢复生成器时(通过在迭代器上调用__next__
),该函数将再次在该点继续。生成器暂停时,无法调用with
语句__exit__
方法,因此无论如何恢复生成器,都不能退出上下文管理器 。>
如果使用@contextmanager
decorator创建一个简单的上下文管理器(它本身依赖于生成器来实现!),您会看到这种情况:
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"
当您从生成器中提取值进行打印时,您将看到:
>>> 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'
请注意,只有在我们检索到第三个值后,上下文才会退出!在第二次next()
调用之后,代码在with
块内的某个点暂停,只有在未暂停时才能退出上下文,并退出{{1}的finally
套件}功能可以运行。