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

将aiohttp脚本转为asyncio+requests(Ubuntu下aiohttp无法运行)

问题:将aiohttp脚本改为requests+asyncio后出现TypeError循环报错

问题背景

原aiohttp脚本在macOS上可正常运行,但Ubuntu环境下aiohttp无法工作。经测试,单独使用requests或简单的asyncio+requests组合能正常访问目标网站,于是将原脚本改为requests版本,却出现TypeError循环报错。

原aiohttp代码

import aiohttp
import asyncio

async def get_data(session, x):
    while True:
        try:
            async with session.get(url=f'https://api.abc.com/{x}') as response:
                if response.status == 200:
                    data = await response.json()
                    try:
                        data = float(data)
                        return data
                    except ValueError:
                        print("Data is not a valid float. Retrying...")
                else:
                    print("Received non-200 status code. Retrying...")
            await asyncio.sleep(1)  # Wait for 1 second before retrying
        except Exception as e:
            print("Unable to get url {} due to {}. Retrying...".format(x, e.__class__))
            await asyncio.sleep(1)  # Wait for 1 second before retrying

async def main(datas):
    async with aiohttp.ClientSession() as session:
        ret = await asyncio.gather(*[get_data(session, data) for data in datas])
        return {datas[i]: ret[i] for i in range(len(datas))}  # Return the results as a dictionary

datas = ['x1', 'x2', 'x3', 'x4']
results = asyncio.run(main(datas))

修改后的requests代码

import asyncio
import requests

async def get_data(x):
    while True:
        try:
            response = requests.get(url=f'https://api.abc.com/{x}')
            if response.status_code == 200:
                try:
                    data = float(response.json())
                    return data
                except ValueError:
                    print("Data is not a valid float. Retrying...")
            else:
                print("Received non-200 status code. Retrying...")
            await asyncio.sleep(1)  # Wait for 1 second before retrying
        except Exception as e:
            print("Unable to get url {} due to {}. Retrying...".format(x, e.__class__))
            await asyncio.sleep(1)  # Wait for 1 second before retrying

async def main(datas):
    tasks = [get_data(data) for data in datas]
    ret = await asyncio.gather(*tasks)
    return {datas[i]: ret[i] for i in range(len(datas))}  # Return the results as a dictionary

datas = ['x1', 'x2', 'x3', 'x4']
results = asyncio.run(main(datas))
print(results)

报错信息

Unable to get data for x1 due to <class 'TypeError'>. Retrying...
Unable to get data for x2 due to <class 'TypeError'>. Retrying...
Unable to get data for x3 due to <class 'TypeError'>. Retrying...
Unable to get data for x4 due to <class 'TypeError'>. Retrying...
Unable to get data for x1 due to <class 'TypeError'>. Retrying...
...

解决方案

问题根源是requests.get是同步阻塞函数,在asyncio协程中直接调用会堵塞事件循环,导致异常捕获逻辑紊乱。正确做法是用asyncio.to_thread将同步的requests调用放到线程池执行,避免堵塞事件循环。

修改后的正确代码:

import asyncio
import requests

async def get_data(x):
    while True:
        try:
            # 用to_thread将同步请求包装为异步操作
            response = await asyncio.to_thread(requests.get, url=f'https://api.abc.com/{x}')
            if response.status_code == 200:
                try:
                    data = float(response.json())
                    return data
                except ValueError:
                    print("数据不是有效的浮点数,重试中...")
            else:
                print("收到非200状态码,重试中...")
            await asyncio.sleep(1)
        except Exception as e:
            print(f"无法获取{x}的数据,错误类型:{type(e)},重试中...")
            await asyncio.sleep(1)

async def main(datas):
    tasks = [get_data(data) for data in datas]
    ret = await asyncio.gather(*tasks)
    return {datas[i]: ret[i] for i in range(len(datas))}

datas = ['x1', 'x2', 'x3', 'x4']
results = asyncio.run(main(datas))
print(results)

版本兼容说明

如果你的Python版本低于3.9(asyncio.to_thread是3.9新增特性),可以用loop.run_in_executor替代:

loop = asyncio.get_running_loop()
response = await loop.run_in_executor(None, requests.get, f'https://api.abc.com/{x}')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 20:50:54