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

如何正确使用asyncio创建任务并通过任务列表实现批量异步执行

asyncio异步调用问题修复方案

现有代码的核心问题

  • 异步协程内调用了同步阻塞的client.get_data()方法:asyncio的事件循环遇到同步阻塞逻辑时会被完全卡住,无法切换到其他协程执行,因此整体执行效率和串行完全一致,无法发挥异步并发优势。
  • 之前调整asyncio.create_task位置报错的原因:asyncio.create_task必须在已经启动的事件循环上下文内调用,如果在同步函数中提前创建task,此时事件循环还未启动,就会抛出协程相关异常。
  • 全局变量data_list的使用没有必要:asyncio.gather会自动按顺序收集所有协程的返回结果,依赖全局变量反而会引入异步并发写的潜在风险。

修复后代码

import asyncio

async def api_single_call(client, symbol):
    # 优先使用客户端提供的异步接口,如果没有异步接口用下方线程池方案执行同步调用
    # 方案1:使用原生异步接口
    data = await client.get_data_async(symbol=symbol)
    # 方案2:同步接口转异步(Python3.9+)
    # data = await asyncio.to_thread(client.get_data, symbol=symbol)
    # 方案3:同步接口转异步(Python3.8及以下版本兼容)
    # data = await asyncio.get_event_loop().run_in_executor(None, client.get_data, symbol)
    return data

def get_ticker_list(client):
    return get_info_tickers(client)

async def main(client):
    tickers = get_ticker_list(client)
    # 正确的create_task调用位置:事件循环已启动的async函数内部
    task_list = [asyncio.create_task(api_single_call(client, symbol)) for symbol in tickers]
    # 自动收集所有协程返回结果,无需全局变量
    data_list = await asyncio.gather(*task_list)
    print(data_list)

asyncio.run(main(client))

关键注意事项

  • 如果client.get_data是HTTP请求类的IO操作,优先替换为异步HTTP客户端实现原生异步调用,比线程池转异步的性能更高。
  • 不要在异步协程内执行CPU密集型计算,此类场景不适合用asyncio实现并发,应该使用多进程方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 07:39:03