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

在异步函数内的同步函数中运行异步函数的报错解决方案(基于asyncio)

问题分析与解决方案

你的问题核心在于**asyncio.run()不能在已经运行的事件循环中调用**——这个函数的作用是初始化并启动一个全新的事件循环,而当你在a()里调用b()时,a()本身已经处于由asyncio.run(a())启动的事件循环中,此时再调用asyncio.run(c())就会触发RuntimeError。另外的协程未被等待警告也是因为这个错误导致c()的执行流程被中断,没有被正确处理。

当然可以仅用asyncio解决这个问题,下面提供两种常见的解决方案:

方案1:将同步函数改为异步函数(推荐)

如果b()没有必须保持同步的理由,把它改成异步函数,然后直接在调用时使用await,这是最符合异步编程规范的做法:

import asyncio
async def c():
    print("yes")
async def b():
    await c()  # 直接await协程,不需要再用asyncio.run
async def a():
    await b()
asyncio.run(a())

这样整个调用链都是异步的,所有协程都会被正确等待执行,运行后会正常输出yes。

方案2:保持b()为同步函数,使用当前事件循环提交任务

如果b()必须保持同步(比如包含其他无法异步化的逻辑),可以获取当前正在运行的事件循环,将c()作为任务提交到循环中:

import asyncio
async def c():
    print("yes")
def b():
    # 获取当前运行的事件循环
    loop = asyncio.get_running_loop()
    # 提交协程为任务,返回任务对象
    return loop.create_task(c())
async def a():
    # 获取b()返回的任务,等待它完成
    task = b()
    await task
asyncio.run(a())

这里loop.create_task()会把c()加入到当前的事件循环中执行,通过await task可以确保a()会等待c()执行完成后再结束,避免程序提前退出导致c()没机会运行。

补充说明

  • 如果你不需要等待c()完成,只是希望它在后台运行,也可以不用await task,但需要注意主协程结束前要给后台任务留出执行时间(比如加await asyncio.sleep(0.1)),否则事件循环会直接关闭,任务会被取消。
  • asyncio.run()只应该作为整个异步程序的入口点使用,不要在异步函数内部嵌套调用它。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 06:23:12