如何解决同时运行Discord.py客户端与Uvicorn应用的阻塞问题
问题根因
- 配置错误:uvicorn设置
workers=3仅在主进程启动模式生效,在线程中运行时该配置失效,还会干扰事件循环绑定 - 事件循环冲突:discord.py的
client.run()是阻塞调用,会独占当前线程的事件循环,你启动的uvicorn子线程未手动初始化独立事件循环,异步逻辑无法正常执行 - 语法错误:你定义的
on_ready回调多带了self参数,事件触发时会抛出异常,影响服务运行
推荐解决方案(同事件循环部署,轻量适配)
直接将两个异步服务挂载到同一个事件循环中运行,无需多线程处理,代码修改如下:
# main.py 修正版 import asyncio from discord.ext.commands import Bot import uvicorn # 导入api.py中的FastAPI实例 from api import app # discord.py v2.x需要显式配置intents import discord intents = discord.Intents.default() # 按需开启需要的权限,比如接收消息内容需要开启message_content intents.message_content = True client = Bot(command_prefix="!", intents=intents) @client.event async def on_ready(): print(f"Bot online, logged in as {client.user}") # 启动FastAPI服务的协程 async def run_api(): config = uvicorn.Config( app, host="127.0.0.1", port=8000, log_level="info" ) server = uvicorn.Server(config) await server.serve() async def main(): # 先启动API服务作为后台任务 asyncio.create_task(run_api()) # 再启动Discord机器人 await client.start("你的机器人TOKEN") if __name__ == "__main__": asyncio.run(main())
注意事项
- 不要给uvicorn配置
loop和workers参数,直接使用当前事件循环即可,多worker模式无法和Discord bot共享事件循环 - 替换代码中的TOKEN为你实际的机器人令牌,按需调整Bot的命令前缀和intents权限
生产环境最优方案(多进程分离部署)
如果需要更高的稳定性和API扩容能力,直接将两个服务拆分为独立进程运行,完全避免耦合:
- 单独运行Discord机器人:
python main.py(main.py仅保留机器人相关逻辑,去掉API相关代码) - 单独运行FastAPI服务:
uvicorn api:app --host 127.0.0.1 --port 8000 --workers 3 - 两个服务之间如果需要通信,通过HTTP接口调用或者Redis中间件实现即可。
内容的提问来源于stack exchange,提问作者Shizuka Yashiro
相关产品推荐
相关产品推荐

