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

无法捕获关闭asyncio事件循环引发的RuntimeError如何解决?

解决asyncio信号处理中RuntimeError捕获失败的问题

问题原因

你当前的try-except捕获不到错误,是因为RuntimeError不是在self.loop.stop()执行时直接抛出的——这个错误是asyncio.run()内部的run_until_complete()方法抛出的。当你在信号处理函数里调用loop.stop(),事件循环提前终止,但asyncio.run还在等待传入的主协程完成,因此会触发这个错误,而它的抛出栈不在你的signal_handler的try块范围内,所以捕获无效。

解决方案

方案1:在asyncio.run调用处捕获错误

直接在调用asyncio.run的代码外层添加try-except,就能捕获到这个RuntimeError:

def main(self, link):
    try:
        asyncio.run(video.get_file(obj.metadata['name']+"_v."+obj.default_video_stream[1], obj.default_video_stream[0]))
    except RuntimeError as e:
        if "Event loop stopped before Future completed" in str(e):
            print('SIGINT or SIGTSTP raised')
            print("cleaning and exiting")
        else:
            # 处理其他类型的RuntimeError
            raise

方案2:优雅终止主任务(推荐)

不要直接调用loop.stop(),而是取消当前运行的主协程,等待清理完成后再停止循环,这样可以避免触发这个RuntimeError:

async def signal_handler(self):
    print('SIGINT or SIGTSTP raised')
    # 获取当前运行的主任务
    main_task = asyncio.current_task()
    if main_task:
        main_task.cancel()
    # 执行你的清理协程
    # await self.cleanup_coroutine()
    # 等待任务取消完成后停止循环
    await asyncio.sleep(0.1)
    self.loop.stop()

同时,在你的主协程get_file里要处理CancelledError:

async def get_file(self, filename, stream):
    try:
        # 你的原有逻辑
        ...
    except asyncio.CancelledError:
        # 可选:在这里做局部清理
        print("任务被取消,执行局部清理")
        raise  # 必须重新抛出,让asyncio处理取消流程

这样修改后,信号触发时会主动取消主任务,清理完成后再停止循环,asyncio.run会正常处理取消流程,不会抛出那个RuntimeError。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:37:13