aiohttp中启动/关闭信号失效求助:绑定函数未执行
解决aiohttp中on_startup信号不生效的问题
你碰到的这个问题很常见,根源在于你用loop.create_server(app.make_handler())手动启动服务器的方式,并没有触发aiohttp内置的应用生命周期钩子——make_handler()只是生成了处理HTTP请求的处理器,并不会自动调用你注册的on_startup这类信号函数。
下面给你两种解决方案,按需选择:
方案一:用官方推荐的web.run_app()启动应用
这是最省心的方式,web.run_app()已经封装了所有应用生命周期的处理逻辑,包括自动调用on_startup、on_shutdown等钩子。修改后的代码如下:
from aiohttp import web import asyncio async def on_startup(app): app['key'] = "need to save something here" print("启动钩子执行成功!") app = web.Application() app.on_startup.append(on_startup) if __name__ == "__main__": web.run_app(app, host='0.0.0.0', port=8080)
启动后你就能看到打印的日志,app['key']也会被正确赋值,完全不用手动管生命周期的触发。
方案二:手动管理事件循环时,主动触发生命周期信号
如果你因为特殊需求必须手动创建服务器,那就要在代码里主动调用应用的生命周期方法,来触发注册的钩子。示例代码如下:
from aiohttp import web import asyncio async def on_startup(app): app['key'] = "need to save something here" print("启动钩子执行成功!") async def on_shutdown(app): print("关闭钩子执行成功!") app = web.Application() app.on_startup.append(on_startup) app.on_shutdown.append(on_shutdown) async def main(): # 先触发所有启动钩子 await app.startup() try: handler = app.make_handler() srv = await loop.create_server(handler, host='0.0.0.0', port=8080) print(f"服务器已启动:http://0.0.0.0:8080") # 让服务器保持运行,直到收到中断信号(比如Ctrl+C) await asyncio.Event().wait() finally: # 触发关闭钩子并清理资源 await app.shutdown() await app.cleanup() srv.close() await srv.wait_closed() if __name__ == "__main__": loop = asyncio.get_event_loop() try: loop.run_until_complete(main()) except KeyboardInterrupt: pass finally: loop.close()
这里的核心是:启动服务器前调用await app.startup(),它会自动执行所有你注册的on_startup函数;关闭服务器时,通过await app.shutdown()和await app.cleanup()触发关闭相关的钩子,确保资源被正确释放。
总结一下,优先选方案一,它能帮你避开很多手动处理生命周期的坑;如果必须用方案二,记得一定要主动调用对应的生命周期方法哦。
内容的提问来源于stack exchange,提问作者Yurii Rabeshko
相关产品推荐
相关产品推荐

