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

Python3.6中asyncio.wait_for超时未取消任务引发RuntimeError求助

Python 3.6 asyncio.wait_for超时后任务未取消问题解答

问题原因

  1. Python 3.6版本的asyncio.wait_for存在实现缺陷:当等待超时触发后,仅会向外抛出TimeoutError异常,但不会正确取消内部包裹的协程任务。代码中第一次调用的reader.read(1)协程在超时后仍然处于挂起等待数据的状态,没有被销毁。
  2. asyncio的StreamReader设计上不支持并发读取操作,内部有专门的状态校验逻辑:当检测到已有一个读协程处于等待数据的状态时,新发起的读调用就会抛出你遇到的RuntimeError: read() called while another coroutine is already waiting for incoming data异常。

解决办法

  • 方案1:升级Python版本到3.7及以上。Python 3.7及之后的官方版本已经修复了asyncio.wait_for的这个缺陷,超时后会自动取消内部等待的协程,你现有的代码不需要做任何修改即可正常运行。
  • 方案2:如果必须兼容Python 3.6环境,可以手动将读操作封装为Task,超时后显式取消Task并等待其取消完成,修改后的代码示例如下:
import sys
import asyncio
import socket

async def test_single_call():
    reader, writer = await asyncio.open_connection(host='127.0.0.1', port=8888)
    # 把读操作封装为独立Task
    read_task = asyncio.ensure_future(reader.read(1))
    try:
        msg = await asyncio.wait_for(read_task, timeout=3)
        print("Unexcepted message received:" , msg, file=sys.stderr)
        assert False
    except asyncio.TimeoutError:
        # 超时后手动取消读任务
        read_task.cancel()
        # 等待任务取消完成,处理取消异常
        try:
            await read_task
        except asyncio.CancelledError:
            pass

    msg = await reader.read(1)

loop = asyncio.get_event_loop()
loop.run_until_complete(test_single_call())
loop.close()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 11:48:02