使用aiohttp搭建API启动Discord Bot时遇协程未等待错误求助
问题解决
错误原因
- 协程未被触发执行:
my_Bot()是异步函数(协程),直接调用不会启动执行,必须通过await或任务调度触发。 bot.run()阻塞事件循环:discord.py 的bot.run()是同步阻塞方法,会独占线程并启动独立事件循环,导致 aiohttp 的服务彻底卡住,无法处理后续请求。
修复后的完整代码
import os from dotenv import load_dotenv import asyncio from aiohttp import web import discord from discord.ext import commands load_dotenv() app = web.Application() bot_instance = None # 全局变量存储机器人实例,避免重复启动 async def index(request): global bot_instance state = request.rel_url.query.get('state') if state == 'start' and bot_instance is None: # 用任务调度启动机器人,不阻塞当前请求响应 asyncio.create_task(my_Bot()) return web.json_response({'state': 'Online'}) elif bot_instance is not None: return web.json_response({'state': 'Already Online'}) return web.FileResponse('index.html') app.router.add_get('/', index) app.router.add_get('/index', index) app.router.add_get('/index.html', index) async def get_token(request): token = os.getenv('TOKEN') return web.json_response({'token': token}) app.router.add_get('/token', get_token) async def my_Bot(): global bot_instance bot = commands.Bot(command_prefix='>', self_bot=True) bot_instance = bot @bot.event async def on_ready(): print('Logged in as') print(bot.user.name) print(bot.user.id) print('------') @bot.command() async def ping(ctx): await ctx.send('pong') try: # 用异步的start方法替代阻塞的run,和aiohttp共享事件循环 await bot.start(os.getenv('TOKEN')) except KeyboardInterrupt: await bot.close() if __name__ == '__main__': web.run_app(app)
关键修复细节
- 补全
aiohttp.web导入:原代码缺失该导入会直接报错,先补上基础依赖。 - 异步任务调度:用
asyncio.create_task()启动机器人协程,既触发执行又不阻塞aiohttp的请求响应流程。 - 替换机器人启动方法:用
await bot.start()替代bot.run(),前者是异步非阻塞方法,能和aiohttp共享同一个事件循环。 - 实例重复启动防护:全局变量
bot_instance记录机器人状态,避免多次请求启动命令导致重复创建实例。 - 参数安全获取:用
query.get('state')替代直接索引,防止无state参数时抛出KeyError。
内容的提问来源于stack exchange,提问作者cdnAshton
相关产品推荐
相关产品推荐

