我正在浏览一个关于快速api的教程,我遇到了类似下面的内容
def get_db():
try:
db = SessionLocal()
yield db
finally:
print("from finally block")
db.close()
@app.get("/")
async def read_all(db: Session = Depends(get_db)):
res = db.query(models.Todos).all()
print("from endpoint")
return res
结果
INFO: 127.0.0.1:39088 - "GET /openapi.json HTTP/1.1" 200 OK
from endpoint
INFO: 127.0.0.1:39088 - "GET / HTTP/1.1" 200 OK
from finally block
为什么Depends(get_db)看起来像某种上下文管理器?。"from finally block"
打印语句直到read_all
方法结束时才执行
做一些类似
class SomeDependency:
def __enter__(self):
print("entering")
def __exit__(self, exc_type, exc_val, exc_tb):
print("exited")
def hello():
try:
yield SomeDependency()
finally:
print("yolo")
if __name__ == "__main__":
next(hello())
finally
块在调用next
之后立即执行。
什么原因get_db
的finally
块在传递给Depends
时没有立即执行?
1条答案
按热度按时间bnl4lu3b1#
你似乎没有清楚地理解上下文管理器和生成器的概念。基本上它们是完全不相关的不同概念。我将简要地解释它们。
上下文管理器是
with
语句特性的一部分,它是try/finally
块的模板代码的语法糖,确保完成事情。请参阅参考资料以了解详细信息。在第二个示例中,没有涉及上下文管理器,因为没有with
语句。生成器是定义迭代器的样板代码的语法糖。(但从实现的Angular 来看,它是一个相当复杂的特性,称为coroutine。)请参阅参考资料以了解详细信息。在第二个示例中,
finally
子句将在hello()
返回的迭代器结束时(当引用计数达到零时)执行。虽然我之前说过这两者完全无关,但实际上还是有一点关系的--定义上下文管理器类的锅炉代码的语法糖,通过生成器定义上下文管理器,如下所示(从参考文献中删除并编辑)。
返回到FastAPI
Depends
,如果你给予一个生成器作为参数,它会使用上面的特性在内部创建一个上下文管理器,你可以看到它的实现。