讲师中心 微信公众号
AI工具推荐 视频效率加速

Python 异步任务的并发与顺序控制

阿晨大大_9840

阿晨大大_9840

发布时间:2026-02-18 16:09:35

|

412人浏览过

|

来源于php中文网

原创

asyncio.gather()是并发启动并等待全部完成的批处理工具,create_task()是立即将协程调度为Task对象以便精细控制;二者协作而非替代,gather适用于不关心响应顺序的并行请求,create_task适用于需穿插await的顺序依赖场景。

python 异步任务的并发与顺序控制

asyncio.gather() 和 asyncio.create_task() 的本质区别

asyncio.gather() 是并发启动、等待全部完成的“批处理工具”,而 asyncio.create_task() 是把协程立刻调度进事件循环、返回一个可随时 await 的 Task 对象。两者不是替代关系,而是协作关系。

常见错误是以为 await asyncio.gather(a(), b()) 能控制执行顺序——其实它只保证“全部开始、全部结束”,中间谁先返回谁后返回完全不可控;而用 create_task() 才能穿插 await 实现精细调度。

  • 需要并行发多个 HTTP 请求且不关心响应顺序 → 用 gather()
  • 想发请求 A,等它返回后再发请求 B,但又不想阻塞整个协程 → 先 create_task(a()),再 await 它,接着 create_task(b())
  • gather() 中任意一个协程抛出异常,所有任务都会被取消(除非加 return_exceptions=True);create_task() 抛异常只影响自身,不影响其他已提交的 Task

用 asyncio.Semaphore 控制并发数,别靠 time.sleep()

很多人用 await asyncio.sleep(0.1) 模拟“错峰”,这既不准又浪费资源:sleep 不等于让出 CPU,只是延迟 await,实际并发数还是由事件循环调度决定,根本压不住连接数或 API 调用频次。

真正可控的方式是 asyncio.Semaphore,它像一道门禁,限制同时最多几个协程能通过关键代码段。

立即学习“Python免费学习笔记(深入)”;

macOS UI 自动化技能包 —— 用 Python 控制你的 Mac
macOS UI 自动化技能包 —— 用 Python 控制你的 Mac

让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限

下载
  • 初始化时指定最大并发数:sem = asyncio.Semaphore(5)
  • 在要限流的代码块前加 async with sem:,自动 acquire/release
  • 注意:Semaphore 不感知任务实际耗时,只管“进的数量”,所以适合 IO 密集型场景(如爬虫、批量 API 调用),不适合 CPU 密集型(得用线程池)
  • 别在循环里反复创建 Semaphore,它应作为共享对象传入或定义为模块级变量

await 一个已经完成的 Task 不会挂起,但 await 同一个协程两次会报错

这是容易混淆的点:create_task() 返回的是 Task 对象,它可被多次 await;而普通协程函数(比如 fetch_data())每次调用都返回新协程对象,只能 await 一次。

典型错误现象:RuntimeError: cannot reuse already awaited coroutine,往往出现在把协程赋值给变量后重复 await。

  • ✅ 正确:task = asyncio.create_task(fetch_data()),然后 await task 多次(第二次直接返回结果)
  • ❌ 错误:coro = fetch_data(),然后 await coro 两次
  • ⚠️ 注意:asyncio.ensure_future() 行为类似 create_task(),但推荐用后者(更明确、有 loop 绑定保障)
  • 如果不确定来源是协程还是 Task,可用 asyncio.iscoroutine() 或 asyncio.isfuture() 判断

asyncio.run() 内部会新建事件循环,别在已有 loop 中调用

在 Jupyter、FastAPI 生命周期、或已运行 asyncio.get_event_loop() 的进程里再调 asyncio.run(main()),会触发 RuntimeError: asyncio.run() cannot be called from a running event loop。

这不是 bug,是设计:asyncio.run() 是为脚本入口准备的“一键启动+清理”封装,它自己管理 loop 生命周期。生产环境里你通常不该手动调它。

  • 脚本主入口(if __name__ == '__main__':)→ 用 asyncio.run(main())
  • Web 框架(如 FastAPI、Starlette)→ 框架已接管 loop,你只写路由协程,不用管 run
  • Jupyter / REPL → 用 await main() 直接执行,或装 nest_asyncio(仅调试)
  • 想复用当前 loop?直接 asyncio.create_task() 或 loop.create_task(),别碰 run()
事情说清了就结束。最常出问题的地方不是语法,而是对 “Task 是什么”“loop 是谁在管”“并发 ≠ 并行” 这几件事没形成直觉。写完记得用 asyncio.current_task() 和 asyncio.all_tasks() 看一眼实际在跑啥。

热门AI工具

更多
蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
Python FastAPI异步API开发_Python怎么用FastAPI构建异步API
Python FastAPI异步API开发_Python怎么用FastAPI构建异步API

Python FastAPI 异步开发利用 async/await 关键字,通过定义异步视图函数、使用异步数据库库 (如 databases)、异步 HTTP 客户端 (如 httpx),并结合后台任务队列(如 Celery)和异步依赖项,实现高效的 I/O 密集型 API,显著提升吞吐量和响应速度,尤其适用于处理数据库查询、网络请求等耗时操作,无需阻塞主线程。

119

2025.12.22

Python 微服务架构与 FastAPI 框架
Python 微服务架构与 FastAPI 框架

本专题系统讲解 Python 微服务架构设计与 FastAPI 框架应用,涵盖 FastAPI 的快速开发、路由与依赖注入、数据模型验证、API 文档自动生成、OAuth2 与 JWT 身份验证、异步支持、部署与扩展等。通过实际案例,帮助学习者掌握 使用 FastAPI 构建高效、可扩展的微服务应用,提高服务响应速度与系统可维护性。

554

2026.02.06

Python Web框架FastAPI 全栈开发教程合集
Python Web框架FastAPI 全栈开发教程合集

以 FastAPI 为核心,讲解现代 Python Web API 的高效开发方式,涵盖路由定义与路径参数/查询参数/请求体绑定、Pydantic 模型的数据校验与序列化、依赖注入(Depends)系统的分层设计、中间件与 CORS 配置、OAuth2 + JWT 认证流程、后台任务(BackgroundTasks)、WebSocket 实时通信、SQLAlchemy 异步 ORM 集成、自动生成 OpenAPI/Swagger 交互文

636

2026.05.09

Python FastAPI异步微服务与高性能接口设计
Python FastAPI异步微服务与高性能接口设计

本专题聚焦 Python FastAPI 框架在高性能接口与微服务开发中的应用,讲解异步请求处理、依赖注入机制、路由设计、数据库异步操作以及接口性能优化策略。结合实际项目案例,帮助开发者构建高并发、低延迟的现代化后端服务架构。

539

2026.06.16

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4378

2023.08.10

http500解决方法
http500解决方法

http500解决方法有检查服务器日志、检查代码错误、检查服务器配置、检查文件和目录权限、检查资源不足、更新软件版本、重启服务器或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3643

2023.11.09

http请求415错误怎么解决
http请求415错误怎么解决

解决方法:1、检查请求头中的Content-Type;2、检查请求体中的数据格式;3、使用适当的编码格式;4、使用适当的请求方法;5、检查服务器端的支持情况。更多http请求415错误怎么解决的相关内容,可以阅读下面的文章。

894

2023.11.14

HTTP 503错误解决方法
HTTP 503错误解决方法

HTTP 503错误表示服务器暂时无法处理请求。想了解更多http错误代码的相关内容,可以阅读本专题下面的文章。

6586

2024.03.12

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

60

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Uvicorn官方安装与入门手册
Uvicorn官方安装与入门手册

共0课时 | 0人学习

Python uv官方项目管理指南
Python uv官方项目管理指南

共0课时 | 0人学习

Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn