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

discord.py非异步函数调用发消息异步函数触发RuntimeError问题咨询

错误原因

你触发报错的核心原因是:asyncio.run() 会创建全新的独立事件循环,但discord.py客户端启动后已经在运行专属的事件循环,所有discord相关的异步操作(比如发消息)必须在这个内置循环中执行,跨循环调用aiohttp请求就会触发"Timeout context manager should be used inside a task"报错。同时firestore的快照回调是在独立子线程中触发的,也不能直接操作主线程的事件循环。

解决方法

直接将你的异步发送任务提交到discord.py内置的事件循环中执行即可,不需要额外创建新循环:

  1. 优先避免异步函数名和参数名重名,防止逻辑冲突
  2. 使用asyncio.run_coroutine_threadsafe跨线程提交协程任务到discord的事件循环,这个方法是线程安全的,适配firestore回调的子线程运行环境
修改后的代码示例

首先修改发送消息的异步函数,避免重名:

async def send_msg(content, channel):
    await channel.send(content)

然后修改checkStart函数中的调用逻辑:

def checkStart(doc_snapshot,changes,read_time):
    for change in changes:
        if change.type.name == 'ADDED' or change.type.name == 'MODIFIED':
            anaDoc = change.document.to_dict()
            if anaDoc['start'] == True:
                # 提交协程到discord内置事件循环执行
                asyncio.run_coroutine_threadsafe(
                    send_msg('Game started!', main_channel[change.document.reference.parent.parent.id]),
                    client.loop
                )
                print(change.document.reference.parent.parent.id)
补充说明

如果你不需要等待消息发送的返回结果,也可以用性能更高的调用方式:

client.loop.call_soon_threadsafe(
    client.create_task,
    send_msg('Game started!', main_channel[change.document.reference.parent.parent.id])
)

不要在discord.py运行过程中使用asyncio.run()创建新循环,否则会持续出现资源冲突类报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 23:48:01