Python 异步编程介绍与代码示例
Python 异步编程介绍与代码示例
一、异步编程概述
异步编程是一种编程范式,它旨在处理那些需要等待I/O操作完成或执行耗时任务的情况。在传统的同步编程中,代码会按照顺序逐行执行,直到遇到一个耗时操作,它会阻塞程序的执行直到该操作完成。这种阻塞式的模型在某些场景下效率低下,因为代码在等待操作完成时无法执行其他任务。异步编程通过非阻塞I/O和协程(coroutine)来提高效率,使得程序在等待某些操作时能够继续执行其他任务,从而提高程序的并发性和响应性。
二、Python 异步编程基础
Python 从 3.4 版本开始引入了 asyncio
库,为异步编程提供了丰富的支持。asyncio
库包括了协程、事件循环(event loop)、任务(task)和期物(future)等关键概念。
-
协程(Coroutine):
协程是一种特殊的函数,可以在执行过程中暂停和恢复。在 Python 中,协程是通过在函数定义前加上async
关键字来创建的。协程内部可以使用await
关键字来暂停自身的执行,等待其他协程或异步操作完成。 -
事件循环(Event Loop):
事件循环是异步编程的核心,它负责调度和执行协程,确保它们按照正确的顺序执行。在 Python 中,asyncio
模块提供了事件循环的实现,开发者可以通过asyncio.get_event_loop()
获取默认的事件循环对象,并使用它来运行协程。 -
任务(Task):
任务是asyncio
库中的一个基本概念,它表示一个异步操作。任务可以通过调用asyncio.create_task()
函数来创建,并返回一个Task
对象。Task
对象本质上是一个特殊的Future
对象,它封装了协程的执行。 -
期物(Future):
期物用于承载协程的执行结果。当协程开始执行时,会创建一个Future
对象与之关联。协程执行完成后,其结果会被存储在Future
对象中。开发者可以通过await
关键字等待Future
对象的结果。
三、async/await 语法
从 Python 3.5 版本开始,可以使用 async
和 await
关键字来编写异步代码。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
会等待所有传入的协程或任务完成,并返回一个包含所有结果的列表。
四、异步编程的优势
-
提高程序效率:
异步编程通过非阻塞I/O和并发执行多个任务,减少了程序在等待操作完成时的空闲时间,从而提高了程序的执行效率。 -
提高程序响应性:
在Web服务器、数据库连接等场景中,异步编程能够更快地响应客户端的请求,提升用户体验。 -
简化复杂逻辑:
异步编程通过协程和事件循环等机制,使得处理复杂逻辑(如回调地狱)变得更加简单和直观。
五、异步编程的注意事项
在进行Python异步编程时,需要注意以下几个方面,以确保代码的正确性、效率和可维护性:
-
避免阻塞操作:
异步编程的核心优势在于非阻塞I/O,因此应尽量避免在协程中执行阻塞操作。如果必须执行阻塞操作,可以通过asyncio.run_in_executor()
方法将其封装在executor中执行,从而避免阻塞事件循环。 -
异常处理:
异步编程中的异常处理需要格外小心。由于异步操作可能在将来的某个时间点完成,因此应使用try-except
语句来捕获和处理可能的异常。此外,asyncio
还提供了asyncio.ensure_future()
函数,可以将协程封装为Future
对象,从而更方便地处理异常。 -
并发度控制:
通过控制并发度,可以平衡程序的性能和资源消耗。如果并发任务过多,可能会导致资源耗尽或性能下降。可以使用asyncio.Semaphore
等同步原语来限制同时执行的任务数量,从而避免这种情况的发生。 -
共享资源访问:
在异步编程中,多个协程可能会同时访问共享资源,这可能导致数据竞争和状态不一致的问题。为了避免这种情况,应使用适当的同步机制(如锁、信号量等)来保护共享资源。 -
事件循环的管理:
在Python的异步编程中,事件循环是核心组件。它负责调度和执行协程,以及处理I/O和系统事件。通常,应使用asyncio.run()
函数来启动和管理事件循环,因为它会自动创建事件循环、运行协程并关闭事件循环。除非有特定需求,否则应避免手动创建和管理事件循环。 -
协程的调度和取消:
在复杂的异步程序中,可能需要动态地调度和取消协程。asyncio
提供了asyncio.create_task()
函数来创建任务(即协程的封装),并提供了任务对象的方法来检查任务状态、取消任务等。 -
调试和日志记录:
异步编程的调试可能比同步编程更复杂,因为程序的执行流程是非线性的。因此,应使用适当的调试工具和日志记录来跟踪程序的执行和定位问题。 -
第三方库和框架的兼容性:
在使用异步编程时,可能会遇到与第三方库和框架的兼容性问题。一些库可能不支持异步操作,或者它们的异步API不够完善。在这种情况下,需要仔细评估是否可以使用这些库,或者寻找替代方案。 -
性能优化:
异步编程虽然可以提高程序的并发性和响应性,但也可能引入额外的性能开销。例如,过多的上下文切换和锁竞争都可能导致性能下降。因此,在进行异步编程时,应注意性能优化,避免不必要的开销。 -
代码的可读性和可维护性:
异步代码的可读性和可维护性通常比同步代码更差,因为异步逻辑更复杂且更难跟踪。因此,在编写异步代码时,应注意代码的清晰性和结构性,避免过度复杂和难以理解的代码。
通过遵循上述注意事项,可以更有效地利用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 的异步编程技术。
相关文章:

Python 异步编程介绍与代码示例
Python 异步编程介绍与代码示例 一、异步编程概述 异步编程是一种编程范式,它旨在处理那些需要等待I/O操作完成或执行耗时任务的情况。在传统的同步编程中,代码会按照顺序逐行执行,直到遇到一个耗时操作,它会阻塞程序的执行直到…...

堆叠的作用
一、为什么要堆叠 传统的园区网络采用设备和链路冗余来保证高可靠性,但其链路利用率低、网络维护成本高,堆叠技术将多台交换机虚拟成一台交换机,达到简化网络部署和降低网络维护工作量的目的。 二、堆叠优势 1、提高可靠性 堆叠系统多台成…...

ubuntu 如何查看某一个网卡的ip地址
在Ubuntu中,你可以使用多种方法来查看某一个网卡的IP地址。以下是一些常用的方法: 使用ip命令: ip命令是现代Linux系统中用于显示和操作路由、网络设备、策略路由和隧道的工具。要查看所有网络接口的IP地址,你可以使用:…...

跨界客户服务:拓展服务边界,创造更多价值
在当今这个日新月异的商业时代,跨界合作已不再是新鲜词汇,它如同一股强劲的东风,吹散了行业间的壁垒,为企业服务创新开辟了前所未有的广阔天地。特别是在客户服务领域,跨界合作正以前所未有的深度和广度,拓…...

linux驱动编程 - kfifo先进先出队列
简介: kfifo是Linux Kernel里面的一个 FIFO(先进先出)数据结构,它采用环形循环队列的数据结构来实现,提供一个无边界的字节流服务,并且使用并行无锁编程技术,即当它用于只有一个入队线程和一个出…...

JS 四舍五入使用整理
一、Number.toFixed() 把数字转换为字符串,结果的小数点后有指定位数的数字,重点返回的数据类型为字符串 toFixed() 方法将一个浮点数转换为指定小数位数的字符串表示,如果小数位数高于数字,则使用 0 来填充。 toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。…...

上万组风电,光伏,用户负荷数据分享
上万组风电,光伏,用户负荷数据分享 可用于风光负荷预测等研究 获取链接🔗 https://pan.baidu.com/s/1izpymx6R3Y8JsFdx42rL0A 提取码:381i 获取链接🔗 https://pan.baidu.com/s/1izpymx6R3Y8JsFdx42rL0A 提取…...

在物联网快速发展的趋势下,Java 怎样优化对低功耗、资源受限的边缘设备的支持,保障物联网应用的稳定运行?
在物联网快速发展的趋势下,Java可以通过以下方式优化对低功耗、资源受限的边缘设备的支持,以保障物联网应用的稳定运行: 精简Java运行环境:针对边缘设备的资源限制,可以使用精简型的Java运行环境,避免不必要…...

java-HashSet 源码分析 1
## 深入分析 Java 中的 HashSet 源码 HashSet 是 Java 集合框架中的一个重要类,它基于哈希表实现,用于存储不重复的元素。HashSet 允许 null 元素,并且不保证元素的顺序。本文将详细分析 HashSet 的源码,包括其数据结构、构造方法…...

K8S 部署 EFK
安装说明 系统版本为 Centos7.9 内核版本为 6.3.5-1.el7 K8S版本为 v1.26.14 ES官网 开始安装 本次安装使用官方ECK方式部署 EFK,部署的是当前的最新版本。 在 Kubernetes 集群中部署 ECK 安装自定义资源 如果能打开这个网址的话直接用这个命令安装,打不开的话…...

AI Earth应用—— 在线使用sentinel数据VV和VH波段进行水体提取分析(昆明抚仙湖、滇池为例)
AI Earth 本文的主要目的就是对水体进行提取,这里,具体的操作步骤很简单基本上是通过,首页的数据检索,选择需要研究的区域,然后选择工具箱种的水体提取分析即可,剩下的就交给阿里云去处理,结果如下: 这是我所选取的一景影像: 详情 卫星: Sentinel-1 级别: 1 …...

基于Hadoop平台的电信客服数据的处理与分析③项目开发:搭建基于Hadoop的全分布式集群---任务9:HBase的安装和部署
任务描述 任务内容为HBase的安装部署与测试。 任务指导 HBase集群需要整个集群所有节点安装的HBase版本保持一致,并且拥有相同的配置 具体配置步骤如下: 1. 解压缩HBase的压缩包 2. 配置HBase的环境变量 3. 修改HBase的配置文件,HBase…...

go语言day09 通道 协程的死锁
Go语言学习——channel的死锁其实没那么复杂 - JackieZheng - 博客园 (cnblogs.com) 目录 通道 创建通道 1)无缓冲通道 2)有缓冲通道 通道的使用 1) 值从通道入口进 2) 值从通道出口出 信道死锁: 0)死锁现场0 1)死…...

黑马的ES课程中的不足
在我自己做项目使用ES的时候,发现了黑马没教的方法,以及一些它项目的小问题 搜索时的匹配方法 这个boolQuery().should 我的项目是通过文章的标题title和内容content来进行搜索 但是黑马它的项目只用了must 如果我们的title和content都用must&#x…...

STM32 中断编程入门
目录 一、中断系统 1、中断的原理 2、中断类型 外部中断 定时器中断 DMA中断 3、中断处理函数 中断标志位清除 中断服务程序退出 二、实际应用 中断控制LED 任务要求 代码示例 中断控制串口通信 任务要求1 代码示例 任务要求2 代码示例 总结 学习目标&…...

使用maven搭建一个SpingBoot项目
1.首先创建一个maven项目 注意选择合适的jdk版本 2.添加依赖 2.在pom.xml中至少添加依赖 spring-boot-starter-web 依赖,目的是引入Tomcat,以及SpringMVC等,使项目具有web功能。 <!-- 引入 包含tomcat,SpringMVC,…...

使用 HTTPS 已成为网站的标配了
网站使用HTTPS的原因 背景:十年前,HTTPS并不普遍,但随着网络安全意识的提高,现在已成为网站标配。 网站升级到HTTPS的动机 安全问题:HTTP缺乏安全机制,易被窃取和篡改数据。例如,电信运营商劫…...

前后端分离Nginx
背景 旧的部署方式是将前端代码打包进后端包的resource server {listen 80;listen 443 ssl;server_name xxx.test.com;location / {proxy_pass http://xxx.test.com;} }后端:https:// xxx.test.com/simcard/querySimcard 前端:https:// x…...

【简单讲解下Tauri】
🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…...

mac上挂载linux目录
在 macOS 上挂载 CentOS 目录步骤: 在挂载前确保 macOS 和 CentOS 在同一个局域网内,并且可以相互访问。如果有网络配置问题,可能会导致挂载失败或连接被拒绝的错误。 要在 macOS 上将 CentOS 的 /disk2/go 目录通过 NFS 挂载到 /Users/zon…...

Linux系统的服务——以Centos7为例
一、Linux系统的服务简介 服务是向外部提供对应功能的进程,其运行在系统后台,能够7*24小时持续不断的提供外界随时发来的服务请求,且服务进程常驻在内存中,具有固定的端口号,通过端口号就能找到服务内容。 提供服务的一…...

Numpy矩阵运算
版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl Numpy概述 Numpy是Python的一个开源数值计算扩展库,主要用于存储和处理大型多维数组和矩阵,并且提供了大量的数学函数来操作这些数组。Numpy是Pytho…...

Spring容器Bean之XML配置方式
一、首先看applicationContext.xml里的配置项bean 我们采用xml配置文件的方式对bean进行声明和管理,每一个bean标签都代表着需要被创建的对象并通过property标签可以为该类注入其他依赖对象,通过这种方式Spring容器就可以成功知道我们需要创建那些bean实…...

【Rust入门】生成随机数
文章目录 前言随机数库rand添加rand库到我们的工程生成一个随机数示例代码 总结 前言 在编程中,生成随机数是一种常见的需求,无论是用于数据分析、游戏开发还是模拟实验。Rust提供了强大的库来帮助我们生成随机数。在这篇文章中,我们将通过一…...

普通Java工程如何在代码中引用docker-compose.yml中的environment值
文章目录 一、概述二、常规做法1. 数据库配置分离2. 代码引用配置3. 编写启动类4. 支持打包成可执行包5. 支持可执行包打包成docker镜像6. docker运行 三、存在问题分析四、改进措施1. 包含environment 变量的编排文件2. 修改读取配置文件方式3. 为什么可以这样做 五、运行效果…...

微观特征轮廓尺寸测量:光学3D轮廓仪、共焦显微镜与台阶仪的应用
随着科技进步,显微测量仪器以满足日益增长的微观尺寸测量需求而不断发展进步。多种高精度测量仪器被用于微观尺寸的测量,其中包括光学3D表面轮廓仪(白光干涉仪)、共聚焦显微镜和台阶仪。有效评估材料表面的微观结构和形貌…...

Rust开发环境搭建
Rust开发环境搭建 环境 rust: 1.79.0(2024-06-13)1. Rustup下载器在线安装 windows: https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe unix: curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh2. R…...

图文识别0难度上手~基于飞浆对pdf简易ocr并转txt
前言 本篇pdf适用windows对视觉识别0基础的的纯小白用户。大佬请绕道~~ 注意: 本项目pdf的ocr对于表格、画图文字,水印等干扰没做任何处理,因此希望各位使用该功能的pdf尽量不要含有这些干扰项,以免影响翻译效果。 流程 1.构建…...

FFmpeg常用命令手册
官方文档:ffmpeg Documentation 常规选项 -i input_url 输入文件或者输入流的路径 Main 选项 -f fmt (input/output) 强制指定输入或输出文件的格式, 常见的格式名称包括flv,mp4、hls、mpegts、avi、mov -c[:stream_specifier] codec (i…...

CTF入门知识点
CTF知识点 md5函数 <?php$a 123;echo md5($a,true); ?> 括号中true显示输出二进制 替换成false显示输出十六进制绕过 ffifdyop 这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是 or 6 而 Mysql 刚好又会把 …...