深入解析 Python 异步编程中的 `gather`、`as_completed` 和 `wait`

news2024/12/26 22:43:24

在现代 Python 开发中,异步编程已经成为了构建高性能、可扩展应用的关键技术之一。通过 asyncio 库,Python 提供了强大的异步功能,帮助开发者更好地管理并发任务,提升程序的效率和响应能力。asyncio 中的三个重要函数——gatheras_completedwait,是处理多个异步任务时非常有用的工具。

本文将深入介绍这三个函数,帮助你理解它们的工作原理、用法及适用场景,提升你在异步编程中的能力。

什么是异步编程?

异步编程是一种通过非阻塞方式处理并发任务的编程模型。在 Python 中,异步编程的核心是协程(coroutine)。协程允许你编写并发代码,但不需要像传统线程那样消耗额外的系统资源。asyncio 库是 Python 提供的官方库,用于处理异步编程,它使用事件循环(event loop)来调度和管理协程的执行。

在并发任务的处理中,如何有效地管理多个任务、等待任务的结果以及控制任务的执行顺序是非常重要的。asyncio 提供了多个工具来帮助开发者实现这一目标,其中 gatheras_completedwait 是最常用的三个函数。

1. asyncio.gather: 并行执行多个任务

什么是 gather

asyncio.gather 是一个非常强大的工具,它可以并行执行多个异步任务,并在所有任务完成后收集它们的结果。它接受多个协程任务作为参数,执行所有任务并等待它们完成。当所有任务都执行完毕后,gather 会返回一个包含所有任务结果的列表。

使用场景

  • 适用于并行执行多个任务,并在所有任务完成后收集结果。
  • 如果任务之间没有依赖关系,gather 是并行执行任务时的理想选择。

示例代码

import asyncio

async def task_1():
    await asyncio.sleep(1)
    return "Task 1 completed"

async def task_2():
    await asyncio.sleep(2)
    return "Task 2 completed"

async def task_3():
    await asyncio.sleep(3)
    return "Task 3 completed"

async def main():
    # 并行执行多个任务
    results = await asyncio.gather(task_1(), task_2(), task_3())
    print(results)  # ['Task 1 completed', 'Task 2 completed', 'Task 3 completed']

# 执行
asyncio.run(main())

输出结果:

['Task 1 completed', 'Task 2 completed', 'Task 3 completed']

在此示例中,asyncio.gather 并行执行了三个任务,并且最终返回了所有任务的执行结果。注意,gather 会等待所有任务完成才返回结果。

异常处理

如果某个任务在执行过程中抛出异常,gather 会立即抛出该异常。你可以通过 return_exceptions=True 参数使 gather 返回异常,而不是直接抛出。

async def task_with_error():
    raise ValueError("An error occurred!")

async def main_with_error():
    try:
        await asyncio.gather(task_1(), task_with_error())
    except Exception as e:
        print(f"Caught an exception: {e}")

# 执行
asyncio.run(main_with_error())

输出结果:

Caught an exception: An error occurred!

通过 return_exceptions=True,你可以捕获到异常并继续执行其他任务。

2. asyncio.as_completed: 按任务完成顺序获取结果

什么是 as_completed

asyncio.as_completed 是一个生成器函数,它允许你按任务完成的顺序获取任务的结果,而不是等待所有任务完成后才返回。这意味着它会在任务完成时逐个返回任务的结果。这个特性对于需要处理任务执行顺序的场景非常有用。

使用场景

  • 适用于需要按任务完成的顺序逐个处理任务结果的场景。
  • 当任务的执行时间不确定且任务间没有明确的顺序时,使用 as_completed 可以更有效地处理结果。

示例代码

import asyncio

async def task_1():
    await asyncio.sleep(2)
    return "Task 1 completed"

async def task_2():
    await asyncio.sleep(1)
    return "Task 2 completed"

async def main():
    tasks = [task_1(), task_2()]
    # 使用 as_completed 按任务完成顺序获取结果
    for result in asyncio.as_completed(tasks):
        print(await result)

# 执行
asyncio.run(main())

输出结果:

Task 2 completed
Task 1 completed

在此示例中,虽然 task_1task_2 后开始执行,但是由于 task_2 执行时间更短,因此它首先完成,并且 as_completed 会首先返回它的结果。

异常处理

gather 类似,as_completed 也可以在任务抛出异常时捕获并抛出。你可以在使用 async for 循环时捕获异常。

async def task_with_error():
    await asyncio.sleep(1)
    raise ValueError("An error occurred!")

async def main_with_error():
    tasks = [task_1(), task_with_error()]
    for result in asyncio.as_completed(tasks):
        try:
            print(await result)
        except Exception as e:
            print(f"Caught an exception: {e}")

# 执行
asyncio.run(main_with_error())

输出结果:

Task 2 completed
Caught an exception: An error occurred!

3. asyncio.wait: 等待任务完成并进行批量处理

什么是 wait

asyncio.wait 是一个更灵活的函数,它允许你等待多个任务,并返回已完成的任务和未完成的任务。你可以通过设置 return_when 参数来控制何时返回结果。例如,设置为 asyncio.ALL_COMPLETED 表示等所有任务完成后返回,而 asyncio.FIRST_COMPLETED 则表示一旦有任务完成就返回。

使用场景

  • 适用于等待多个任务,并根据任务的完成情况进行批量处理的场景。
  • 你可以根据不同的条件(如任务完成或抛出异常)来灵活控制任务的执行。

示例代码

import asyncio

async def task_1():
    await asyncio.sleep(1)
    return "Task 1 completed"

async def task_2():
    await asyncio.sleep(2)
    return "Task 2 completed"

async def main():
    tasks = [task_1(), task_2()]
    done, pending = await asyncio.wait(tasks, return_when=asyncio.ALL_COMPLETED)
    for task in done:
        print(await task)

# 执行
asyncio.run(main())

输出结果:

Task 1 completed
Task 2 completed

使用 return_when 参数

asyncio.wait 允许你根据不同的条件返回已完成的任务。例如,设置 return_when=asyncio.FIRST_COMPLETED 可以让你在第一个任务完成时返回结果。

async def main():
    tasks = [task_1(), task_2()]
    done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
    for task in done:
        print(await task)

# 执行
asyncio.run(main())

输出结果:

Task 1 completed

总结

  • asyncio.gather:适用于并行执行多个任务,等待所有任务完成并返回它们的结果。
  • asyncio.as_completed:适用于按任务完成顺序逐个处理任务的结果,尤其是在任务完成时间不确定的场景下。
  • asyncio.wait:适用于等待多个任务,并灵活地控制返回已完成的任务,支持不同的条件和超时处理。

通过合理选择这三个函数,你可以有效地管理和协调异步任务的执行,控制并发任务的数量,优化程序性能,并处理不同任务的执行顺序。这些工具对于构建高性能的异步应用是非常有帮助的。

希望本文能帮助你更好地理解和应用 asyncio 中的这三个重要函数。如果你有任何问题或想法,欢迎在评论区交流!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2252479.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

arkTS:使用ArkUI实现用户信息的持久化管理与自动填充(PersistentStorage)

arkUI:使用ArkUI实现用户信息的持久化管理与自动填充(PersistentStorage) 1 主要内容说明2 例子2.1 登录页2.1.1登陆页的相关说明2.1.1.1 持久化存储的初始化2.1.1.2 输入框2.1.1.3 记住密码选项2.1.1.4 登录按钮的逻辑2.1.1.5 注册跳转 2.1.…

基于SpringBoot+Vue的美妆购物网站

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

【SpringBoot+Vue】x-admin管理系统跟做

技术栈 前端技术说明Vue前端框架Vuex全局状态管理框架ElementUI前端UI框架Axios前端HTTP框架vue-element-admin项目脚手架 后端技术说明SpringBoot容器MVC框架MyBatisORM框架MyBatis-plusMyBatis增强工具Redis非关系型数据库 数据库准备 SET NAMES utf8mb4; SET FOREIGN_KE…

【Docker】Docker配置远程访问

配置Docker的远程访问,你需要按照以下步骤进行操作: 1. 在Docker宿主机上配置Docker守护进程监听TCP端口 Docker守护进程默认只监听UNIX套接字,要实现远程访问,需要修改配置以监听TCP端口。 ‌方法一:修改Docker服务…

LeetCode hot100(自用背诵、部分题目、非最优解)

点击题目可以跳转到LeetCode 哈希 两数之和 public int[] twoSum(int[] nums, int target) {int lengthnums.length;int[] ans new int[2];for (int i 0; i <length-1 ; i) {for (int j i1; j < length; j) {if(nums[i]nums[j]target){ans[0]i;ans[1]j;}}}return an…

Android -- 简易音乐播放器

Android – 简易音乐播放器 播放器功能&#xff1a;* 1. 播放模式&#xff1a;单曲、列表循环、列表随机&#xff1b;* 2. 后台播放&#xff08;单例模式&#xff09;&#xff1b;* 3. 多位置同步状态回调&#xff1b;处理模块&#xff1a;* 1. 提取文件信息&#xff1a;音频文…

基础Web安全|SQL注入

基础Web安全 URI Uniform Resource Identifier&#xff0c;统一资源标识符&#xff0c;用来唯一的标识一个资源。 URL Uniform Resource Locator&#xff0c;统一资源定位器&#xff0c;一种具体的URI&#xff0c;可以标识一个资源&#xff0c;并且指明了如何定位这个资源…

ESG研究报告白皮书与ESG治理报告合集(2020-2023年)

一.资料范围&#xff1a;&#xff08;1&#xff09;ESG白皮书及指南;&#xff08;2&#xff09;ESG研究报告,&#xff08;3&#xff09;ESG治理报告分析&#xff08;4&#xff09;上市公司ESG报告&#xff08;知名企业&#xff09; 二、资料用途&#xff1a;可以分析研究企业E…

WPF指示灯的实现方式

WPF指示灯的实现方式 样式 XAML <Button x:Name"Btn1" Width"25" Height"25" Grid.Row"0" Grid.Column"1" Margin"10 5 5 5 "><Button.Template><ControlTemplate TargetType"Button"…

初识QT第一天

思维导图 利用Qt尝试做出原神登陆界面 import sys from PyQt6.QtGui import QIcon, QPixmap, QMovie from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QLineEdit# 封装原神窗口类 class Genshin(QWidget):# 构造函数def __init__(self):# 初始化父类…

【Linux】线程池设计 + 策略模式

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; 线程池 1-1 ⽇志与策略模式1-2 线程池设计1-3 线程安全的单例模式1-3-1 什么是单例模式1-3-2 单例模式的特点1-3-3 饿汉实现⽅式和懒汉实现⽅式1-3-4 饿汉…

vim插件管理器vim-plug替代vim-bundle

文章目录 vim-plug与vim-bundle对比vim-plug安装vim-plug管理安装插件相关文章 vim-plug与vim-bundle对比 vim-plug 和 vim-bundle 都是 Vim 的插件管理器&#xff0c;但它们有一些关键的区别。以下是两者的主要对比&#xff1a; 易用性和简洁性 vim-plug: 易用性: vim-plug …

107.【C语言】数据结构之二叉树求总节点和第K层节点的个数

目录 1.求二叉树总的节点的个数 1.容易想到的方法 代码 缺陷 思考:能否在TreeSize函数内定义静态变量解决size的问题呢? 其他写法 运行结果 2.最好的方法:分而治之 代码 运行结果 2.求二叉树第K层节点的个数 错误代码 运行结果 修正 运行结果 其他写法 1.求二…

【代码随想录day48】【C++复健】739. 每日温度;496.下一个更大元素 I;503.下一个更大元素II

739. 每日温度 一顿操作猛如虎&#xff0c;一看击败5%。一眼顶针&#xff0c;鉴定为在存栈的时候把值和下标一起存了&#xff0c;所以导致了问题。 class Solution { public:vector<int> dailyTemperatures(vector<int>& temperatures) {stack<vector<…

vscode + conda + qt联合开发

安装vscode 安装conda 清华大学开源软件镜像(Anaconda下载)_清华大学镜像-CSDN博客 conda create新建一个环境&#xff0c;激活这个环境&#xff0c;然后安装pyside6 pip install pyside6 -i https://pypi.tuna.tsinghua.edu.cn/simple 安装成功后输入 pip list查看是否安装…

第十一篇 绘图matplotlib.pyplot的使用

文章目录 摘要安装方法入门案例使用plt绘图使用ax绘图plt.figure参数plot参数案例一 绘制红色实心的点状图案例二 绘制红色的破折线图案例三 绘制两条线颜色总结设置标题、轴名称、图例使用plt实现绘图使用ax实现绘图legend()中loc设置刻度plt自定义刻度ax自定义刻度plt.title …

Unity-Particle System属性介绍(一)基本属性

什么是ParticleSystem 粒子系统是Unity中用于模拟大量粒子的行为的组件。每个粒子都有一个生命周期&#xff0c;包括出生、运动、颜色变化、大小变化和死亡等。粒子系统可以用来创建烟雾、火焰、水、雨、雪、尘埃、闪电和其他各种视觉效果。 开始 在项目文件下创建一个Vfx文件…

计算机的错误计算(一百七十二)

摘要 探讨 MATLAB 对于算式 的计算误差。 例1. 在 MATLAB 中计算 的值。 直接贴图吧&#xff1a; 这样&#xff0c;MATLAB 的输出中只有3位正确数字&#xff0c;有效数字的错误率为 (16-3)/16 81.25% . 因为16位的正确输出为 0.2971242332737277e-18&#xff08;ISReals…

Flink四大基石之CheckPoint(检查点) 的使用详解

目录 一、Checkpoint 剖析 State 与 Checkpoint 概念区分 设置 Checkpoint 实战 执行代码所需的服务与遇到的问题 二、重启策略解读 重启策略意义 代码示例与效果展示 三、SavePoint 与 Checkpoint 异同 操作步骤详解 四、总结 在大数据流式处理领域&#xff0c;Ap…

S4 UPA of AA :新资产会计概览

通用并行会计&#xff08;Universal Parallel Accounting&#xff09;可以支持每个独立的分类账与其他模块集成&#xff0c;UPA主要是为了支持平行评估、多货币类型、财务合并、多准则财务报告的复杂业务需求 在ML层面UPA允许根据不同的分类账规则对物料进行评估&#xff0c;并…