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

discord.py 2.0导入函数触发“asyncio.run()不能在运行事件循环中调用”错误求助

问题原因
  • 用asyncio.run(main())启动discord.py bot时,这个函数会创建并管理一个全新的事件循环。
  • 加载扩展时,如果扩展文件直接从主文件导入内容,会导致主文件的代码被重新执行一遍,而此时原事件循环还在运行状态,再次调用asyncio.run(main())就会触发错误——asyncio.run()本身不允许在已有运行中的事件循环里嵌套调用。
修复方案

方案1:重构代码,拆分共享逻辑

把需要在主文件和扩展中复用的函数、常量,单独抽离到一个独立的模块(比如utils.py),主文件和扩展都从这个模块导入,彻底避免互相导入的问题。
示例:

  1. 创建utils.py存放共享代码:
    async def my_shared_task():
        # 这里写需要复用的逻辑
        pass
    
  2. 主文件导入:
    from utils import my_shared_task
    
  3. 扩展文件导入:
    from utils import my_shared_task
    

方案2:给主文件加执行入口判断

在主文件里用if __name__ == "__main__":把asyncio.run(main())包裹起来,这样当扩展导入主文件时,这段启动代码不会被执行。
示例:

import discord
from discord.ext import commands

async def main():
    bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())
    # 加载扩展、注册事件等逻辑
    await bot.start("你的Bot令牌")

# 只有直接运行主文件时才执行启动代码
if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

方案3:复用已有事件循环(不推荐)

如果实在没法重构代码,可以在扩展里直接使用bot当前运行的事件循环,不要尝试重新启动。这种方式会增加代码耦合,尽量少用。
示例:

from discord.ext import commands

@commands.command()
async def example(ctx):
    # 用bot已有的事件循环执行异步任务
    await ctx.bot.loop.create_task(my_shared_task())
核心思路

问题本质是模块重复导入导致启动代码被多次执行,触发了两次asyncio.run()。解决方向要么是通过入口判断避免导入时启动bot,要么是拆分共享代码消除互相导入的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 05:21:14