FastAPI+Uvicorn+pycord运行报错:Future所属事件循环不一致
FastAPI + py-cord 在Uvicorn生产模式下的事件循环冲突问题
问题现象
- 结合py-cord的FastAPI应用整体可运行,但Discord机器人响应缓慢
- 生产模式启动时抛出错误:
ValueError: The future belongs to a different loop than the one specified as the loop argument
- 开发模式(带
reload=True)启动无报错,机器人响应正常;生产模式启动触发错误
当前启动py-cord的代码:
@asynccontextmanager async def lifespan(app: FastAPI): asyncio.create_task(client.start(DISCORD_TOKEN)) yield client.close() app = FastAPI(lifespan=lifespan)
核心原因
开发模式下Uvicorn会重新加载模块并初始化单一事件循环,而生产模式直接传入app对象时,py-cord客户端可能提前绑定了默认的asyncio事件循环,和FastAPI运行时的循环不一致,导致future归属冲突。
修复方案
方案1:强制绑定FastAPI的事件循环给py-cord
修改lifespan函数,确保py-cord客户端使用当前运行的事件循环:
import asyncio from contextlib import asynccontextmanager from fastapi import FastAPI import discord client = discord.Client(intents=discord.Intents.all()) DISCORD_TOKEN = "your-discord-token" @asynccontextmanager async def lifespan(app: FastAPI): # 获取FastAPI当前使用的事件循环 current_loop = asyncio.get_running_loop() # 将py-cord客户端的loop绑定到当前循环 client.loop = current_loop # 启动机器人任务 asyncio.create_task(client.start(DISCORD_TOKEN)) yield # 优雅关闭客户端(改用await确保清理完成) await client.close() app = FastAPI(lifespan=lifespan)
方案2:统一生产模式启动方式
生产模式下不要直接传入app对象给uvicorn.run,保持和开发模式一致的模块引用方式:
if __name__ == "__main__": import uvicorn # 用字符串引用app,而非直接传对象 uvicorn.run("main:app", host="0.0.0.0", port=5000, log_level="info")
这种方式下Uvicorn会重新初始化事件循环,确保py-cord和FastAPI使用同一个循环。
方案3:切换到discord.py(已验证有效)
若上述方案仍无法解决,直接替换py-cord为discord.py是最稳妥的选择——discord.py在事件循环兼容性上的处理更成熟,和FastAPI协作时不会出现此类循环冲突问题。
内容的提问来源于stack exchange,提问作者Alan Janczuk
相关产品推荐
相关产品推荐

