You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python FastAPI/Uvicorn技术问题:如何向uvicorn.run()传递Queue?

解决方案:给FastAPI(Uvicorn运行)传递跨进程Queue

针对你遇到的问题,核心原因是Uvicorn的reload=True模式会启动额外的监控进程,导致普通的multiprocessing.Queue无法在子进程中复用;同时直接通过字符串导入app的方式会触发模块重新加载,全局变量失效。下面提供两种可行方案:

方案一:关闭热重载(reload),直接传递FastAPI实例

如果不需要开发时的热重载功能,这种方案最简单可靠:

from multiprocessing import Queue
from multiprocessing import Process
import uvicorn
from fastapi import FastAPI, WebSocket, WebSocketDisconnect

class WSServer:
    def run(self, queue):
        # 直接在run方法内创建FastAPI实例,并将队列绑定到app的state中
        app = FastAPI()
        app.state.queue = queue

        @app.websocket("/")
        async def websocket_endpoint(websocket: WebSocket):
            await websocket.accept()
            try:
                while True:
                    msg = await websocket.receive_text()
                    # 直接通过app.state访问队列
                    app.state.queue.put(f"收到WebSocket消息:{msg}")
                    # 也可以从队列取数据推送给客户端
                    # if not app.state.queue.empty():
                    #     await websocket.send_text(app.state.queue.get())
            except WebSocketDisconnect:
                pass

        # 直接传入app实例,关闭reload
        uvicorn.run(app, host="0.0.0.0", port=8081, reload=False, access_log=False) 

main_queue: Queue = Queue() 
proc = Process(target=WSServer().run, name="Process: Simple Server", args=(main_queue,))
proc.start()
proc.join()

原理

关闭reload后,Uvicorn不会启动监控进程,直接在当前进程内运行服务。我们直接创建FastAPI实例并绑定队列,避免了模块重新加载导致的全局变量失效问题。

方案二:保留热重载,使用Manager创建共享队列

如果必须保留reload功能,需要用multiprocessing.Manager创建跨进程共享的Queue——这种队列基于进程间通信实现,不受Uvicorn子进程的影响:

from multiprocessing import Manager, Process
import uvicorn
from fastapi import FastAPI, WebSocket, WebSocketDisconnect

# 必须在主进程创建Manager和共享队列,确保所有子进程都能访问
manager = Manager()
main_queue = manager.Queue()

app = FastAPI()
app.state.queue = main_queue

@app.websocket("/")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    try:
        while True:
            msg = await websocket.receive_text()
            app.state.queue.put(f"收到WebSocket消息:{msg}")
            # 示例:从队列取数据发送给客户端
            # if not app.state.queue.empty():
            #     await websocket.send_text(app.state.queue.get())
    except WebSocketDisconnect:
        pass

class WSServer:
    def run(self):
        # 开启reload模式,使用共享队列不受影响
        uvicorn.run("__main__:app", host="0.0.0.0", port=8081, reload=True, access_log=False) 

# 启动服务进程
proc = Process(target=WSServer().run, name="Process: Simple Server")
proc.start()
proc.join()

原理

multiprocessing.Manager会启动一个独立的管理进程,所有通过它创建的队列都会通过这个进程进行数据转发,不管Uvicorn启动多少子进程,都能访问到同一个队列实例。

为什么你之前的尝试失败

  • 直接给uvicorn.run()传Queue:该函数没有接收自定义对象的参数,无法直接传递。
  • 全局变量:reload模式下Uvicorn会重新导入模块,全局变量会被重新初始化,原来的Queue对象无法复用。
  • 传递内存地址:进程间内存是隔离的,无法通过内存地址直接获取其他进程的对象。

内容的提问来源于stack exchange,提问作者MJey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 03:00:52