如何在Python中同时启动FastAPI与Socket.IO服务(Uvicorn问题)
解决FastAPI与Socket.IO同进程部署的问题
问题背景
要开发一个同时提供FastAPI接口和Socket.IO服务的Python应用,遇到两个核心问题:
- 主线程调用
uvicorn.run()会阻塞,只能启动第一个服务 - 多线程分别启动两个Uvicorn服务时,触发
ValueError: signal only works in main thread错误
解决方案
无需启动多个Uvicorn实例或依赖多线程,直接将FastAPI和Socket.IO整合到同一个ASGI应用中,用单Uvicorn进程启动即可,这也是ASGI架构的原生优势。
关键调整点
- 将Socket.IO从WSGI模式改为ASGI模式,适配FastAPI的ASGI架构
- 用
socketio.ASGIApp把Socket.IO服务与FastAPI应用绑定,让同一个端口同时处理HTTP请求和Socket.IO连接
修改后的完整代码
import json from fastapi import FastAPI import socketio import uvicorn # 创建FastAPI应用 app_api = FastAPI() # 创建Socket.IO ASGI服务器(指定async_mode为asgi) sio = socketio.AsyncServer(async_mode="asgi") # 整合Socket.IO与FastAPI:Socket.IO绑定默认路径,其余请求转发给FastAPI app_sio = socketio.ASGIApp(sio, other_app=app_api) # FastAPI路由示例 @app_api.get("/") def read_root(): return {"Hello": "World"} # Socket.IO全局事件监听 @sio.on('*', namespace="/aws-iam") async def catch_all(event, sid, data): print(event, sid, data) if __name__ == "__main__": # 启动整合后的ASGI应用,仅需一个Uvicorn实例 uvicorn.run(app_sio, host='127.0.0.1', port=8000, reload=True, debug=True)
报错原因说明
- 多线程启动Uvicorn并开启
reload=True时,Uvicorn的重载机制会尝试在子线程中注册信号处理器,但Python的信号处理仅允许在主线程执行,因此触发错误。 - 原方案分开启动两个服务属于资源冗余,ASGI架构原生支持在同一个应用中同时处理HTTP、WebSocket及Socket.IO请求,整合是最优实现方式。
内容的提问来源于stack exchange,提问作者user1315621
相关产品推荐
相关产品推荐

