Python 异步编程介绍与代码示例

Python 异步编程介绍与代码示例

一、异步编程概述

异步编程是一种编程范式,它旨在处理那些需要等待I/O操作完成或执行耗时任务的情况。在传统的同步编程中,代码会按照顺序逐行执行,直到遇到一个耗时操作,它会阻塞程序的执行直到该操作完成。这种阻塞式的模型在某些场景下效率低下,因为代码在等待操作完成时无法执行其他任务。异步编程通过非阻塞I/O和协程(coroutine)来提高效率,使得程序在等待某些操作时能够继续执行其他任务,从而提高程序的并发性和响应性。

二、Python 异步编程基础

Python 从 3.4 版本开始引入了 asyncio 库,为异步编程提供了丰富的支持。asyncio 库包括了协程、事件循环(event loop)、任务(task)和期物(future)等关键概念。

  1. 协程(Coroutine)
    协程是一种特殊的函数,可以在执行过程中暂停和恢复。在 Python 中,协程是通过在函数定义前加上 async 关键字来创建的。协程内部可以使用 await 关键字来暂停自身的执行,等待其他协程或异步操作完成。

  2. 事件循环(Event Loop)
    事件循环是异步编程的核心,它负责调度和执行协程,确保它们按照正确的顺序执行。在 Python 中,asyncio 模块提供了事件循环的实现,开发者可以通过 asyncio.get_event_loop() 获取默认的事件循环对象,并使用它来运行协程。

  3. 任务(Task)
    任务是 asyncio 库中的一个基本概念,它表示一个异步操作。任务可以通过调用 asyncio.create_task() 函数来创建,并返回一个 Task 对象。Task 对象本质上是一个特殊的 Future 对象,它封装了协程的执行。

  4. 期物(Future)
    期物用于承载协程的执行结果。当协程开始执行时,会创建一个 Future 对象与之关联。协程执行完成后,其结果会被存储在 Future 对象中。开发者可以通过 await 关键字等待 Future 对象的结果。

三、async/await 语法

从 Python 3.5 版本开始,可以使用 asyncawait 关键字来编写异步代码。async 关键字用于定义一个协程函数,而 await 关键字用于在协程中暂停执行,等待其他协程或异步操作完成。

示例 1:简单的异步函数
import asyncioasync def my_coroutine():print("Coroutine started")await asyncio.sleep(1)  # 模拟异步操作print("Coroutine resumed")return "Result"async def main():result = await my_coroutine()print(f"Result: {result}")asyncio.run(main())

在这个示例中,my_coroutine 是一个协程函数,它使用 await asyncio.sleep(1) 来模拟一个耗时操作。main 函数也是一个协程函数,它使用 await 关键字等待 my_coroutine 的执行结果。最后,通过 asyncio.run(main()) 启动事件循环,并运行 main 协程。

示例 2:并发执行多个异步任务
import asyncioasync def task(name, delay):print(f"Executing task: {name}")await asyncio.sleep(delay)print(f"Task {name} finished")async def main():tasks = [task("Task 1", 2), task("Task 2", 1), task("Task 3", 3)]await asyncio.gather(*tasks)asyncio.run(main())

在这个示例中,我们定义了三个异步任务 task,每个任务都有一个名称和延迟时间。在 main 函数中,我们使用 asyncio.gather(*tasks) 来并发执行这些任务。asyncio.gather 会等待所有传入的协程或任务完成,并返回一个包含所有结果的列表。

四、异步编程的优势
  1. 提高程序效率
    异步编程通过非阻塞I/O和并发执行多个任务,减少了程序在等待操作完成时的空闲时间,从而提高了程序的执行效率。

  2. 提高程序响应性
    在Web服务器、数据库连接等场景中,异步编程能够更快地响应客户端的请求,提升用户体验。

  3. 简化复杂逻辑
    异步编程通过协程和事件循环等机制,使得处理复杂逻辑(如回调地狱)变得更加简单和直观。

五、异步编程的注意事项

在进行Python异步编程时,需要注意以下几个方面,以确保代码的正确性、效率和可维护性:

  1. 避免阻塞操作
    异步编程的核心优势在于非阻塞I/O,因此应尽量避免在协程中执行阻塞操作。如果必须执行阻塞操作,可以通过asyncio.run_in_executor()方法将其封装在executor中执行,从而避免阻塞事件循环。

  2. 异常处理
    异步编程中的异常处理需要格外小心。由于异步操作可能在将来的某个时间点完成,因此应使用try-except语句来捕获和处理可能的异常。此外,asyncio还提供了asyncio.ensure_future()函数,可以将协程封装为Future对象,从而更方便地处理异常。

  3. 并发度控制
    通过控制并发度,可以平衡程序的性能和资源消耗。如果并发任务过多,可能会导致资源耗尽或性能下降。可以使用asyncio.Semaphore等同步原语来限制同时执行的任务数量,从而避免这种情况的发生。

  4. 共享资源访问
    在异步编程中,多个协程可能会同时访问共享资源,这可能导致数据竞争和状态不一致的问题。为了避免这种情况,应使用适当的同步机制(如锁、信号量等)来保护共享资源。

  5. 事件循环的管理
    在Python的异步编程中,事件循环是核心组件。它负责调度和执行协程,以及处理I/O和系统事件。通常,应使用asyncio.run()函数来启动和管理事件循环,因为它会自动创建事件循环、运行协程并关闭事件循环。除非有特定需求,否则应避免手动创建和管理事件循环。

  6. 协程的调度和取消
    在复杂的异步程序中,可能需要动态地调度和取消协程。asyncio提供了asyncio.create_task()函数来创建任务(即协程的封装),并提供了任务对象的方法来检查任务状态、取消任务等。

  7. 调试和日志记录
    异步编程的调试可能比同步编程更复杂,因为程序的执行流程是非线性的。因此,应使用适当的调试工具和日志记录来跟踪程序的执行和定位问题。

  8. 第三方库和框架的兼容性
    在使用异步编程时,可能会遇到与第三方库和框架的兼容性问题。一些库可能不支持异步操作,或者它们的异步API不够完善。在这种情况下,需要仔细评估是否可以使用这些库,或者寻找替代方案。

  9. 性能优化
    异步编程虽然可以提高程序的并发性和响应性,但也可能引入额外的性能开销。例如,过多的上下文切换和锁竞争都可能导致性能下降。因此,在进行异步编程时,应注意性能优化,避免不必要的开销。

  10. 代码的可读性和可维护性
    异步代码的可读性和可维护性通常比同步代码更差,因为异步逻辑更复杂且更难跟踪。因此,在编写异步代码时,应注意代码的清晰性和结构性,避免过度复杂和难以理解的代码。

通过遵循上述注意事项,可以更有效地利用Python的异步编程能力,编写出高效、可靠和可维护的异步应用程序。

六、异步编程中的错误处理

在异步编程中,错误处理是一个重要的方面。由于异步操作可能在将来的某个时间点完成,并且可能成功或失败,因此我们需要一种机制来捕获和处理这些错误。

示例 3:异步错误处理
import asyncioasync def risky_operation():# 假设这是一个可能引发异常的异步操作await asyncio.sleep(1)raise ValueError("Something went wrong!")async def main():try:await risky_operation()except ValueError as e:print(f"Caught an exception: {e}")asyncio.run(main())

在这个示例中,risky_operation 是一个可能抛出异常的异步函数。在 main 函数中,我们使用 try-except 块来捕获并处理这个异常。

七、异步上下文管理器

在 Python 中,上下文管理器(通过 with 语句使用)常用于资源管理,如文件操作、数据库连接等。在异步编程中,我们也有异步上下文管理器的需求。

从 Python 3.7 开始,asyncio 库引入了 async with 语法,允许我们使用异步上下文管理器。

示例 4:异步上下文管理器
import asyncioclass AsyncContextManager:async def __aenter__(self):print("Entering context")# 初始化代码,如打开数据库连接return selfasync def __aexit__(self, exc_type, exc_val, exc_tb):print("Exiting context")# 清理代码,如关闭数据库连接return False  # 如果需要抑制异常,则返回 Trueasync def main():async with AsyncContextManager():print("Inside the context")await asyncio.sleep(1)asyncio.run(main())

在这个示例中,AsyncContextManager 类定义了异步上下文管理器的行为。__aenter__ 方法在进入上下文时执行,__aexit__ 方法在退出上下文时执行。注意,__aexit__ 方法必须返回一个布尔值,用于指示是否需要抑制异常。

八、异步编程与并发

虽然异步编程和并发编程经常一起讨论,但它们并不完全相同。异步编程主要关注于单个线程内的非阻塞操作,而并发编程则涉及多个线程或进程同时执行多个任务。然而,在 Python 的 asyncio 库中,我们可以通过异步编程实现并发效果,因为事件循环能够同时调度多个协程的执行。

九、高级话题:异步生成器

Python 3.6 引入了异步生成器(async generators),它们是结合了异步编程和生成器特性的强大工具。异步生成器允许你编写一个可以异步产生值的函数,这些值可以在需要时逐个获取,而无需一次性加载到内存中。

示例 5:异步生成器
import asyncioasync def async_generator():for i in range(5):await asyncio.sleep(1)  # 模拟异步操作yield iasync def main():async for value in async_generator():print(value)asyncio.run(main())

在这个示例中,async_generator 是一个异步生成器函数,它使用 yield 关键字来异步产生值。在 main 函数中,我们使用 async for 循环来逐个获取这些值。

十、总结

Python 的异步编程通过 asyncio 库提供了强大的支持,使得编写高效、响应迅速的异步应用程序成为可能。通过协程、事件循环、任务和期物等概念,Python 的异步编程模型能够处理复杂的异步逻辑,并优化程序的执行效率。然而,异步编程也带来了一些挑战,如错误处理和并发控制等。通过深入学习这些概念,并结合实际的应用场景,我们可以更好地利用 Python 的异步编程能力来构建高效、可靠的应用程序。

以上就是对 Python 异步编程的一个基本介绍和代码示例。希望这些信息能够帮助你理解并掌握 Python 的异步编程技术。

在这里插入图片描述

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

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

相关文章

Codeforces Round 903 (Div. 3)A~F

A.Dont Try to Count 输入样例: 12 1 5 a aaaaa 5 5 eforc force 2 5 ab ababa 3 5 aba ababa 4 3 babb bbb 5 1 aaaaa a 4 2 aabb ba 2 8 bk kbkbkbkb 12 2 fjdgmujlcont tf 2 2 aa aa 3 5 abb babba 1 19 m mmmmmmmmmmmmmmmmmmm输出样例: 3 1 2 -1 1 0…

1999-2022年企业持续绿色创新水平数据

企业持续绿色创新水平数据为研究者提供了评估企业在绿色技术领域创新持续性和能力的重要视角。以下是对企业持续绿色创新水平数据的介绍: 数据简介 定义:企业持续绿色创新水平反映了企业在一定时期内绿色专利申请的持续性和创新能力。计算方法&#xf…

初识STM32:开发方式及环境

STM32的编程模型 假如使用C语言的方式写了一段程序,这段程序首先会被烧录到芯片当中(Flash存储器中),Flash存储器中的程序会逐条的进入CPU里面去执行。 CPU相当于人的一个大脑,虽然能执行运算和执行指令,…

通信协议:常见的芯片内通信协议

相关阅读 通信协议https://blog.csdn.net/weixin_45791458/category_12452508.html?spm1001.2014.3001.5482 本文将简单介绍一些常见的芯片间通信协议,但不会涉及到协议的具体细节。 一、AMBA(Advanced Microcontroller Bus Architecture)…

MySQL之备份与恢复(七)

备份与恢复 文件系统快照 规划LVM备份 LVM快照备份也是有开销的。服务器写到原始卷的越多,引发的额外开销也越多。当服务器随机修改许多不同块时,磁头需要需要自写时复制空间来来回回寻址,并且将数据的老版本写到写时复制空间。从快照中读…

刷题之多数元素(leetcode)

多数元素 哈希表解法&#xff1a; class Solution { public:/*int majorityElement(vector<int>& nums) {//map记录元素出现的次数&#xff0c;遍历map&#xff0c;求出出现次数最多的元素unordered_map<int,int>map;for(int i0;i<nums.size();i){map[nu…

最适合mysql5.6安装的linux版本-实战

文章目录 一, 适合安装mysql5.6的linu版本1. CentOS 72. Ubuntu 14.04 LTS (Trusty Tahr)3. Debian 8 (Jessie)4. Red Hat Enterprise Linux (RHEL) 7 二, 具体以Ubuntu 14.04 LTS (Trusty Tahr)为例安装虚拟机安装Ubuntu 14.04 LTS (Trusty Tahr) 自己弄安装ssh(便于远程访问,…

前端八股文 对$nextTick的理解

$nexttick是什么? 获取更新后的dom内容 为什么会有$nexttick ? vue的异步更新策略 (这也是vue的优化之一 要不然一修改数据就更新dom 会造成大量的dom更新 浪费性能) 这是因为 message &#xff08;data&#xff09;数据在发现变化的时候&#xff0c;vue 并不会立刻去更…

240705_昇思学习打卡-Day17-基于 MindSpore 实现 BERT 对话情绪识别

240705_昇思学习打卡-Day17-基于 MindSpore 实现 BERT对话情绪识别 近期确实太忙&#xff0c;此处仅作简单记录&#xff1a; 模型简介 BERT全称是来自变换器的双向编码器表征量&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;&#xff0c…

【wordpress教程】wordpress博客网站添加非法关键词拦截

有的网站经常被恶意搜索&#xff0c;站长们不胜其烦。那我们如何屏蔽恶意搜索关键词呢&#xff1f;下面就随小编一起来解决这个问题吧。 后台设置预览图&#xff1a; 设置教程&#xff1a; 1、把以下代码添加至当前主题的 functions.php 文件中&#xff1a; add_action(admi…

CVPR 2024最佳论文分享:通过解释方法比较Transformers和CNNs的决策机制

CVPR&#xff08;Conference on Computer Vision and Pattern Recognition&#xff09;是计算机视觉领域最有影响力的会议之一&#xff0c;主要方向包括图像和视频处理、目标检测与识别、三维视觉等。近期&#xff0c;CVPR 2024 公布了最佳论文。共有10篇论文获奖&#xff0c;其…

计算组的妙用!!页面权限控制

需求描述&#xff1a; 某些特殊的场景下&#xff0c;针对某页看板&#xff0c;需要进行数据权限卡控&#xff0c;但是又不能对全部的数据进行RLS处理&#xff0c;这种情况下可以利用计算组来解决这个需求。 实际场景 事实表包含产品维度和销售维度 两个维度属于同一公司下面的…

【Python】已解决:FileNotFoundError: [Errno 2] No such file or directory: ‘./1.xml’

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;FileNotFoundError: [Errno 2] No such file or directory: ‘./1.xml’ 一、分析问题背景 在Python编程中&#xff0c;FileNotFoundError是一个常见的异常&…

贝尔曼方程(Bellman Equation)

贝尔曼方程(Bellman Equation) 贝尔曼方程(Bellman Equation)是动态规划和强化学习中的核心概念,用于描述最优决策问题中的价值函数的递归关系。它为状态值函数和动作值函数提供了一个重要的递推公式,帮助我们计算每个状态或状态-动作对的预期回报。 贝尔曼方程的原理 …

Python 自动化测试必会技能板块—unittest框架

说到 Python 的单元测试框架&#xff0c;想必接触过 Python 的朋友脑袋里第一个想到的就是 unittest。 的确&#xff0c;作为 Python 的标准库&#xff0c;它很优秀&#xff0c;并被广泛应用于各个项目。但其实在 Python 众多项目中&#xff0c;主流的单元测试框架远不止这一个…

西门子PLC1200--与电脑S7通讯

硬件构成 PLC为西门子1211DCDCDC 电脑上位机用PYTHON编写 二者通讯用网线&#xff0c;通讯协议用S7 PLC上的数据 PLC上的数据是2个uint&#xff0c;在DB1&#xff0c;地址偏移分别是0和2 需要注意的是DB块要关闭优化的块访问&#xff0c;否则是没有偏移地址的 PLC中的数据内…

elementui中日期/时间的禁用处理,使用传值的方式

项目中,经常会用到 在一个学年或者一个学期或者某一个时间段需要做的某件事情,则我们需要在创建这个事件的时候,需要设置一定的时间周期,那这个时间周期就需要给一定的限制处理,避免用户的误操作,优化用户体验 如下:需求为,在选择学年后,学期的设置需要在学年中,且结束时间大…

软件架构之计算机组成与体系结构

1.1计算机系统组成 计算机系统是一个硬件和软件的综合体&#xff0c;可以把它看成按功能划分的多级层次结构。 1.1.1 计算机硬件的组成 硬件通常是指一切看得见&#xff0c;摸得到的设备实体。原始的冯•诺依曼&#xff08;VonNeumann&#xff09;计算机在结构上是以运算器为…

2024年中国十大杰出起名大师排行榜,最厉害的易经姓名学改名字专家

在2024年揭晓的中国十大杰出易学泰斗评选中&#xff0c;一系列对姓名学与国学易经有深入研究的专家荣登榜单。其中&#xff0c;中国十大权威姓名学专家泰斗顶级杰出代表人物的师傅颜廷利大师以其在国际舞台上的卓越贡献和深邃学识&#xff0c;被公认为姓名学及易经起名领域的权…

verilog读写文件注意事项

想要的16进制数是文本格式提供的文件&#xff0c;想将16进制数提取到变量内&#xff0c; 可以使用 f s c a n f ( f d 1 , " 也可以使用 fscanf(fd1,"%h",rd_byte);实现 也可以使用 fscanf(fd1,"也可以使用readmemh(“./FILE/1.txt”,mem);//fe放在mem[0…