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

使用Asyncio与Uvicorn ASGI Server时队列任务报错问题排查

问题分析与解决

错误根源

这个RuntimeError的核心是事件循环不匹配:

  • 你在全局作用域创建queue = asyncio.Queue(1)时,队列会自动绑定到当前的默认事件循环
  • 但之后你手动创建了新的事件循环loop = asyncio.new_event_loop(),并将其传给Uvicorn的Config,同时在这个新循环中启动了add任务
  • 当队列满(容量为1)或空时,队列内部用于等待的Future属于旧的默认循环,而add任务运行在新循环中,两者冲突就抛出了"Future attached to a different loop"的异常

修复方案

方案1:让队列绑定到新事件循环

把队列的创建放到新循环的上下文里,确保队列、任务、服务器使用同一个事件循环:

import asyncio
from uvicorn import Config, Server
import random


async def add(queue):
  while True:
    await queue.put(str(random.randint(1, 10000)))
    print(queue.qsize())
    await asyncio.sleep(1)


async def app(scope, receive, send):
    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            [b'content-type', b'text/plain'],
        ]
    })
    val = await queue.get()
    queue.task_done()
    await send({
        'type': 'http.response.body',
        'body': bytes(val, 'utf-8'),
    })


loop = asyncio.new_event_loop()
# 将新循环设为默认循环,再创建队列,确保队列绑定到该循环
asyncio.set_event_loop(loop)
queue = asyncio.Queue(1)

loop.create_task(add(queue))
config = Config(app=app, loop=loop)
server = Server(config)
loop.run_until_complete(server.serve())

方案2:让Uvicorn管理事件循环(更简洁推荐)

不需要手动创建和维护事件循环,交给Uvicorn自动处理,只需在启动前把add任务加入Uvicorn使用的循环即可:

import asyncio
from uvicorn import Config, Server
import random

queue = asyncio.Queue(1)

async def add(queue):
  while True:
    await queue.put(str(random.randint(1, 10000)))
    print(queue.qsize())
    await asyncio.sleep(1)


async def app(scope, receive, send):
    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            [b'content-type', b'text/plain'],
        ]
    })
    val = await queue.get()
    queue.task_done()
    await send({
        'type': 'http.response.body',
        'body': bytes(val, 'utf-8'),
    })


async def main():
    # 在主协程中创建任务,自动绑定到Uvicorn使用的事件循环
    asyncio.create_task(add(queue))
    config = Config(app=app)
    server = Server(config)
    await server.serve()

if __name__ == "__main__":
    asyncio.run(main())

为什么方案2更好?

Uvicorn会自动处理事件循环的创建、适配和销毁,完全符合asyncio的最佳实践,避免手动管理循环时容易出现的绑定错误,代码结构也更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 15:05:32