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

Python异步函数多await使用问题:aiohttp与信号量的自定义类实现

分析异步请求函数中多await的合理性与问题点

咱们来拆解你这段get_url异步函数里的多await用法,看看哪些地方合理,哪些地方踩了坑:

核心问题:重复读取响应体的无效await

aiohttp的Response对象是流式响应,响应体只能被读取一次——一旦你调用await response.text()/await response.read()/await response.json()中的任何一个,整个响应流就会被耗尽,后续再调用其他读取方法只会拿到空内容或者直接报错。

你当前代码里连续调用三个读取的await:

text_response = await response.text()
read_response = await response.read()
json_response = await response.json()

这会导致:

  • 只有第一个text_response能拿到正确的响应文本
  • read_response会是空字节串b''
  • json_response会因为响应流已耗尽抛出异常(虽然你捕获了ContentTypeError,但实际这里还会触发其他读取类异常)

修复方案:只读取一次响应体,再派生不同格式结果

应该先一次性读取响应体的原始字节,再基于这个字节串解析文本和JSON:

async with self.session.get(url) as response:
    try:
        # 只读取一次响应体,拿到原始字节
        read_response = await response.read()
        # 从原始字节解析文本(复用响应对象的编码设置)
        text_response = read_response.decode(response.charset or 'utf-8')
        # 尝试将原始字节解析为JSON
        json_response = json.loads(read_response)
        await asyncio.sleep(random.uniform(0.1, 0.5))
    except aiohttp.client_exceptions.ContentTypeError:
        json_response = {}
    # 补充完整status字段
    return {
        'json': json_response,
        'text': text_response,
        'read': read_response,
        'status': response.status
    }

其他await的合理性分析

  1. async with self.semaphore:这个用法完全合理,Semaphore用来限制并发请求数,避免触发目标网站的反爬机制或者超出自身系统的资源限制,是异步批量请求场景的标准操作。
  2. await asyncio.sleep(...):这个延迟的位置需要注意——你现在把它放在try块里,意味着只有当JSON解析成功时才会执行延迟。如果你的目的是不管请求成功失败都要加随机延迟(避免被识别),建议把它移到try-except外面,或者放到finally块中:
try:
    # 读取和解析逻辑
except aiohttp.client_exceptions.ContentTypeError:
    json_response = {}
finally:
    await asyncio.sleep(random.uniform(0.1, 0.5))
  1. 单个读取类await方法:单独调用await response.text()或await response.json()本身是合理的,但不能在同一个Response实例上多次调用读取类的await方法。

小细节补充

你返回字典里的status字段没写完,应该赋值为response.status,这样能返回请求的HTTP状态码,方便后续排查请求异常问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:23:46