管理应用的生命周期:async def lifespan(app: FastAPI)与app = FastAPI(lifespan=lifespan)

我们讲过@asynccontextmanager,参见Python 上下文管理器的使用

也讲过FastAPI,参见基于FastAPI框架的WebSocket服务器

再看看二者综合应用的框架(服务器端):

在FastAPI中,lifespan 事件用于管理应用的生命周期,包括启动和关闭时的逻辑。通过提供一个自定义的 lifespan 函数,你可以在应用启动前和执行某些初始化操作,以及在应用关闭前执行清理操作。

from contextlib import asynccontextmanager  
from fastapi import FastAPI  
from typing import Any, Dict  
import asyncio  
  
# 假设 CommunicationLayer 是一个处理通信的类  
class CommunicationLayer:  
    def __init__(self):  
        # 初始化资源,例如建立连接、启动服务等  
        print("CommunicationLayer initialized")  
  
    async def launch(self, **param: Dict[str, Any]) -> Dict[str, Any]:  
        # 模拟启动过程,这里可以添加实际的启动逻辑  
        # 例如,根据参数启动服务或进程  
        print(f"Launching with parameters: {param}")  
        # 返回一个模拟的响应  
        return {"status": "success", "message": "Service launched"}  
  
    async def shutdown(self) -> None:  
        # 清理资源,例如关闭连接、停止服务等  
        print("CommunicationLayer shutdown")  
  
# 异步上下文管理器,用于在应用生命周期中管理 communicator  
@asynccontextmanager  
async def lifespan(app: FastAPI):  
    global communicator  
    if communicator is None:  
        # 初始化 communicator  
        communicator = CommunicationLayer()  
    try:  
        yield  
    finally:  
        # 确保在应用关闭时关闭 communicator  
        await communicator.shutdown()  
  
app = FastAPI(lifespan=lifespan)  
  
communicator: CommunicationLayer = None  
  
@app.post("/launch")  
async def launch(param: Dict[str, Any]):  
    # 调用 communicator 的 launch 方法  
    return await communicator.launch(**param)  
  
if __name__ == "__main__":  
    import uvicorn  
    uvicorn.run(app, host="0.0.0.0", port=5050)
  1. CommunicationLayer 类:这个类模拟了一个通信层,它包含初始化、启动和关闭的方法。launch 方法接收一个字典参数,并返回一个包含状态信息的字典。shutdown 方法用于清理资源。

  2. lifespan 异步上下文管理器:这个管理器在应用启动时初始化 communicator,并在应用关闭时确保 communicator 被正确关闭。使用 try...finally 结构来确保即使在发生异常时也能执行清理操作。

  3. FastAPI 应用:使用 FastAPI 创建应用,并通过 lifespan 参数传入自定义的生命周期管理器。

  4. 路由:定义了一个 POST 路由 /launch,它接收一个字典参数并调用 communicator 的 launch 方法。

  5. 运行应用:使用 uvicorn 运行 FastAPI 应用。

 async def lifespan(app: FastAPI)与app = FastAPI(lifespan=lifespan) ,看上去是循环定义(你中有我,我中有你),怎么回事?

在Python中,async def lifespan(app: FastAPI) 和 app = FastAPI(lifespan=lifespan) 之间的依赖关系并不是循环定义,而是应用配置和生命周期管理的一种常见模式。这里的关键在于理解函数定义(async def)和函数调用(或作为参数传递)之间的区别。

函数定义与调用

  1. 函数定义async def lifespan(app: FastAPI) 定义了一个名为 lifespan 的异步函数,它接受一个 FastAPI 类型的参数 app。这个定义本身并不执行任何代码,它只是声明了函数的存在和它的参数类型。

  2. 函数调用或作为参数传递app = FastAPI(lifespan=lifespan) 是在创建 FastAPI 应用实例时,将 lifespan 函数作为参数传递给 FastAPI 类的构造函数。这里并没有调用 lifespan 函数(即没有执行 await lifespan(...)),而只是将函数的引用传递给了 FastAPI 实例。

为什么这不是循环定义

  • 定义阶段:在Python解释器读取代码时,它首先会识别并定义所有的函数、类和变量。在这个阶段,lifespan 函数被定义为一个可以接受的参数类型的异步函数。

  • 实例化阶段:当执行到 app = FastAPI(lifespan=lifespan) 时,FastAPI 类的构造函数会接收 lifespan 函数的引用,并将其存储在内部,以便在适当的时候调用。此时,lifespan 函数并没有被实际执行。

  • 执行阶段:当FastAPI应用启动或关闭时,FastAPI框架会负责调用之前传递的 lifespan 函数(实际上是调用你提供的异步上下文管理器),以执行相应的生命周期逻辑。

函数定义和实例化是两个独立的步骤,它们之间的依赖关系是通过参数传递来实现的,而不是通过相互调用或定义来实现的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值