Python并发编程库:Asyncio的异步编程实战
Python并发编程库:Asyncio的异步编程实战
在现代应用中,并发和高效的I/O处理是影响系统性能的关键因素之一。Python的asyncio
库是专为异步编程设计的模块,提供了一种更加高效、易读的并发编程方式,适用于处理大量的I/O密集型任务(如网络请求、文件操作等)。在这篇博客中,我们将详细介绍如何使用asyncio
来进行异步编程,并通过一个实战案例,展示asyncio
如何提升程序的性能。
1. 异步编程基础概念
在开始编码前,我们先理解一些基本概念:
- 同步:任务按顺序依次执行,只有当前任务执行完成后,下一个任务才会开始执行。
- 异步:任务可以并发执行,当遇到I/O操作时,程序可以切换到其他任务执行,从而不必等待。
- 协程(Coroutine):协程是可以被挂起和恢复的函数,用于实现异步执行。在Python中,用
async def
定义协程函数。 - 事件循环(Event Loop):
asyncio
的核心,它负责调度并运行协程,当协程遇到await
时就会释放控制权,切换到其他任务。
2. Asyncio的核心功能
asyncio
库主要由以下几个核心部分组成:
- 事件循环:管理所有异步任务的调度与执行。
- 协程函数:用
async def
定义的函数,可以包含await
关键字,表示程序可以在此处暂停并切换任务。 - 任务(Tasks):将协程封装成任务,让它们在事件循环中并发运行。
- Future对象:表示一个异步操作的最终结果。
2.1 异步协程函数
在asyncio
中,用async def
定义的函数即为协程函数。协程函数只有在被await
调用时才会执行。
import asyncioasync def my_coroutine():print("Start coroutine")await asyncio.sleep(1)print("End coroutine")# 运行协程
asyncio.run(my_coroutine())
2.2 任务的创建
可以使用asyncio.create_task
将协程封装成任务,从而允许多个任务并发执行:
async def task1():print("Task 1 start")await asyncio.sleep(2)print("Task 1 end")async def task2():print("Task 2 start")await asyncio.sleep(1)print("Task 2 end")async def main():task_1 = asyncio.create_task(task1())task_2 = asyncio.create_task(task2())await task_1await task_2asyncio.run(main())
在上面的代码中,两个任务将并发执行。由于task2
的延迟时间较短,因此它会先结束。
2.3 等待多个任务
asyncio.gather
可以等待多个协程并发执行并返回结果:
async def fetch_data(n):print(f"Fetching data {n}")await asyncio.sleep(2)return f"Data {n}"async def main():results = await asyncio.gather(fetch_data(1), fetch_data(2), fetch_data(3))print(results)asyncio.run(main())
在这里,asyncio.gather
会并发运行三个fetch_data
任务,并返回所有任务的结果。
3. Asyncio异步编程实战
下面我们通过一个网络爬虫的例子展示asyncio
的应用。假设我们需要从多个URL中提取数据,如果我们按顺序一个一个地请求这些URL,效率会非常低。我们可以使用asyncio
并发请求这些URL,从而显著提升程序性能。
3.1 使用Asyncio实现简单网络爬虫
我们将使用aiohttp
库实现异步的HTTP请求。aiohttp
是一个支持异步的HTTP客户端,非常适合和asyncio
结合使用。
首先,安装aiohttp
库:
pip install aiohttp
然后,我们编写异步爬虫代码:
import asyncio
import aiohttp# 异步获取单个URL数据
async def fetch_url(session, url):async with session.get(url) as response:return await response.text()# 主函数:使用asyncio.gather并发请求多个URL
async def main(urls):async with aiohttp.ClientSession() as session:tasks = [fetch_url(session, url) for url in urls]results = await asyncio.gather(*tasks)return results# 示例URL列表
urls = ["http://example.com","http://example.org","http://example.net"
]# 运行主函数并获取结果
data = asyncio.run(main(urls))
for i, content in enumerate(data):print(f"Content of URL {i+1}:")print(content[:100]) # 打印前100个字符
在这个代码中,我们并发地请求了多个URL,并获取每个URL的内容。这样做的好处是,程序可以在等待一个URL响应时去处理其他URL请求,极大地提高了效率。
3.2 超时控制与错误处理
在网络请求中,超时和错误处理也是重要的一部分。我们可以为fetch_url
添加超时和异常处理,以确保程序在遇到问题时不会崩溃。
async def fetch_url(session, url):try:async with session.get(url, timeout=5) as response:response.raise_for_status() # 检查响应状态return await response.text()except asyncio.TimeoutError:print(f"Timeout error for URL: {url}")except aiohttp.ClientError as e:print(f"Error fetching URL {url}: {e}")return None # 返回None表示请求失败
在添加了错误处理后,即使某些URL请求失败,程序也会继续执行。
4. 性能对比:同步 vs 异步
为了更直观地感受asyncio
带来的性能提升,我们可以通过对比同步和异步爬虫的执行时间。
4.1 同步版本爬虫
import requests
import timedef fetch_url_sync(url):response = requests.get(url)return response.text# 同步爬虫主函数
def main_sync(urls):results = []for url in urls:results.append(fetch_url_sync(url))return results# 测试同步爬虫
start_time = time.time()
data_sync = main_sync(urls)
end_time = time.time()print(f"同步爬虫耗时: {end_time - start_time} 秒")
4.2 异步版本爬虫
直接运行我们上面的异步爬虫,并计算其执行时间:
start_time = time.time()
data_async = asyncio.run(main(urls))
end_time = time.time()print(f"异步爬虫耗时: {end_time - start_time} 秒")
在多个URL请求的场景下,异步爬虫的执行时间通常会比同步爬虫短得多,这展示了asyncio
在I/O密集型任务中的显著优势。
5. 基础总结
上面介绍了asyncio
的基本概念及其在Python异步编程中的应用,通过代码实例展示了如何使用asyncio
进行异步操作以及如何显著提高程序的并发能力。异步编程虽然学习曲线较高,但在I/O密集型任务中具有明显优势,尤其是在网络请求、文件处理等场景中。
6. 进阶应用:使用信号量和限制并发数量
在实际应用中,异步任务的数量可能非常多(例如几百或几千个URL请求)。如果全部并发执行,可能会导致系统资源耗尽,甚至触发对方服务器的访问限制。asyncio
提供了Semaphore
(信号量)机制,可以限制同时执行的任务数量。
下面是如何使用信号量来限制并发任务数的示例:
async def fetch_url_with_semaphore(semaphore, session, url):async with semaphore: # 使用信号量来限制并发数量try:async with session.get(url, timeout=5) as response:return await response.text()except Exception as e:print(f"Error fetching {url}: {e}")return Noneasync def main_with_semaphore(urls, max_concurrent_tasks=5):semaphore = asyncio.Semaphore(max_concurrent_tasks) # 限制并发数量async with aiohttp.ClientSession() as session:tasks = [fetch_url_with_semaphore(semaphore, session, url) for url in urls]results = await asyncio.gather(*tasks)return results# 设置最大并发任务数为5
start_time = time.time()
data_with_limit = asyncio.run(main_with_semaphore(urls, max_concurrent_tasks=5))
end_time = time.time()
print(f"使用信号量限制的异步爬虫耗时: {end_time - start_time} 秒")
在这个例子中,我们通过信号量控制了最多只有5个任务同时运行,从而有效管理了系统资源的使用。
7. 异步上下文管理器
在异步编程中,我们经常需要创建和关闭连接、打开和关闭文件等,这些操作通常需要使用上下文管理器。Python 3.5引入了异步上下文管理器,允许我们用async with
来管理异步资源。以aiohttp
的Session为例,在异步编程中,这样的上下文管理器能够自动处理连接的关闭,非常方便。
使用异步上下文管理器读取文件
如果需要异步地处理文件操作,可以使用aiofiles
库,该库支持异步读取和写入文件。以下是一个读取文件的简单示例:
首先安装aiofiles
库:
pip install aiofiles
然后在代码中使用它:
import aiofilesasync def read_file_async(file_path):async with aiofiles.open(file_path, mode='r') as file:content = await file.read()return content# 示例
async def main():content = await read_file_async("example.txt")print(content)asyncio.run(main())
使用异步文件操作在处理大文件或需要高并发的文件操作时非常有用,因为它不会阻塞事件循环。
8. 小结
asyncio
提供了强大的异步编程能力,使得Python在处理I/O密集型任务时的效率得到了显著提升。通过本文介绍的实战示例,你已经掌握了asyncio
的核心概念和一些常用技术,包括:
- 如何定义和运行协程函数
- 如何并发地执行多个任务
- 使用
asyncio.gather
批量并发执行任务 - 利用信号量来控制并发任务数量
- 应用异步上下文管理器管理资源
asyncio
不仅适用于网络请求和文件操作,也可以应用于多种场景,例如爬虫、聊天应用、数据采集等。掌握asyncio
之后,你会发现Python的异步编程能够使程序更加高效、流畅,从而提升系统的整体性能。希望你能在实际项目中将这些技术加以应用,打造更高效的异步系统。
相关文章:

Python并发编程库:Asyncio的异步编程实战
Python并发编程库:Asyncio的异步编程实战 在现代应用中,并发和高效的I/O处理是影响系统性能的关键因素之一。Python的asyncio库是专为异步编程设计的模块,提供了一种更加高效、易读的并发编程方式,适用于处理大量的I/O密集型任务…...

vueui vxe-form 分享实现表单项的联动禁用,配置式表单方式的用法
官网文档:https:/vxeui.com 实现表单项的联动禁用 在使用 vxe-form 时,有时候需要将表单项直接进行关联操作,比如某一项选择后,另外一项设置为禁用状态不可选择,使用插槽的话神容易实现,本章是分享配置式的…...

供应SW1655集成功率管的高频率、高性能同步整流
概述 SW1655 是一款集成 N 沟道 MOSFET 的高频率、高性能同步整流功率开关。针对离线式反激 变换器的副边同步整流应用,替代肖特基整流二极管,可以显著提高系统效率的同时,实现高集 成度与高功率密度。 SW1655 具有 VCC 自供电功能&#…...

电动机出现故障后怎么处理?
在工业生产中,电动机作为重要的驱动设备,其运行状态直接关系到生产线的效率和稳定性。然而,由于各种因素的影响,电动机在运行过程中可能会出现多种故障。那么,电动机出现故障后怎么处理? 一、电动机在工业…...

练习LabVIEW第四十题
学习目标: 用labvIEW做一个循环闪烁指示灯,要能够在前面板调节周期和占空比。 开始编写: 前面板 一个布尔指示灯一维数组,两个数值输入控件; 程序框图 添加一个while循环,循环内添加初始化数组&…...

蓝牙BLE开发——红米手机无法搜索蓝牙设备?
解决 红米手机,无法搜索附近蓝牙设备 具体型号当时忘记查看了,如果你遇到有以下选项,记得打开~ 设置权限...

UE5.4 PCG Layered Biomes插件
B站学习链接 官方文档 一、PCGSpawn Preset:负责管理PCG要用到的植被资产有哪些 二、BiomesSettings:设置要使用的植被资产Layer、Spawn参数 1.高度Layer参数: 2.地形Layer:我这里用地形样条线绘制了一块地形Layer 绘制点和…...

搭建你的私人云盘:使用File Browser与cpolar实现公网传输文件
文章目录 前言1.下载安装File Browser2.启动访问File Browser3.安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4.固定公网地址访问 前言 File Browser是一个开源的文件管理器和文件共享工具,它可以帮助用户轻…...

QT/QT QUICK与前端WEB开发的区别
开发框架与目标: QT/QT QUICK:跨平台应用程序开发框架,用于创建图形用户界面(GUI),特别适用于移动和嵌入式设备。前端WEB开发:主要关注Web应用的用户界面,使用HTML、CSS、JavaScript等技术。…...

Python+Playwright(Nuitka、Pyinstaller打包)
安装驱动 playwright install # 这个安装所有默认的浏览器 playwright install chromium # 一般只装这一个浏览器就够了,要是装另外两个浏览器,后面的参数名可以修改查看各个驱动的位置 playwright install --dry-run创建打包目录 在运行的包里面…...

2024年前三季度币安、OKX等五大交易所上币表现分析
随着加密市场竞争的加剧,头部交易所逐渐在上币策略、代币选择、交易活跃度等方面采取了不同的应对策略。Animoca Digital Research近期发布的一份报告,通过对币安、OKX、Bitget、KuCoin和Bybit五大交易所2024年前三季度的上币情况进行了详细分析。本文将…...

Go语言sync.WaitGroup与errgroup.Group用法详解
errgroup.Group 和 sync.WaitGroup 的主要区别在于它们的错误处理和协程管理方式。 errgroup.Group 专为并发操作中的错误捕获设计,任意goroutine返回错误时,会立即终止其他goroutine的执行。 而 sync.WaitGroup 主要用于等待多个 goroutine 完成&…...

【大数据学习 | kafka】kafka的ack和一致性
1. ack级别 上文中我们提到过kafka是存在确认应答机制的,也就是数据在发送到kafka的时候,kafka会回复一个确认信息,这个确认信息是存在等级的。 ack0 这个等级是最低的,这个级别中数据sender线程复制完毕数据默认kafka已经接收到…...

学习虚幻C++开发日志——定时器
官方文档:虚幻引擎中的Gameplay定时器 | 虚幻引擎 5.5 文档 | Epic Developer Community | Epic Developer Community 定时器 安排在经过一定延迟或一段时间结束后要执行的操作。例如,您可能希望玩家在获取某个能力提升道具后变得无懈可击,…...

问政浔川(1)—— 有了浔川社团官方联合会和社团官方,那么浔川总社部是干什么的呢?
问政浔川(1)—— 有了浔川社团官方联合会和社团官方,那么浔川总社部是干什么的呢? 在浔川社团组织的复杂架构中,浔川社团官方联合会和社团官方已广为人知,但对于浔川总社部,很多人仍心存疑惑。这…...

区块链技术应用--电子签章(模块三)
区块链技术应用–电子签章(模块三) 背景描述 电子签章可实现与纸质文件盖章操作相似的可视效果,以保障数据来源的真实性、数据完整性以及签名人行为的不可否认性。 传统的电子签章系统是基于中心化的,也就是数据是集中存储在中心数据库中,这就导致传统电子签章使用记录…...

多面体定义+多面体是凸集+多面体的重要性质
文章目录 多面体定义多面体是凸集多面体重要性质1. 有界多面体(Convex Polytope)2. 无界多面体(Unbounded Polyhedron)3. 极点表示(顶点形式)与极点-极射线表示定理 在数学中, 多面体ÿ…...

为什么 Allow 配合 meta noindex 比使用Disallow好?
为什么 Allow 配合 meta noindex 1、Disallow 的问题 当你使用 Disallow: / 时: 爬虫根本不会访问你的页面 因此永远看不到你的 meta noindex 标签 如果有其他网站链接到你的页面,Google 可能还是会将其编入索引(因为它无法确认你是否真的…...

通讯学徒学习日记
本章内容为 长期更新模式,目前入职的第三天,学徒状态。 文章目录 前言开始接水晶头、接光纤水晶头接光纤 PON(GPON 、EPON)AON 和 PON 的详解AONPON 前言 编程虽然是爱好,但确实也想把这份爱好变成工作。但是对于目前刚…...

迪杰斯特拉算法
迪杰斯特拉算法 LeetCode 743. 网络延迟时间 https://blog.csdn.net/xiaoxi_hahaha/article/details/110257368 import sysdef dijkstra(graph, source):"""dijkstra算法:param graph: 邻接矩阵:param source: 出发点,源点:return:""&…...

IPsec传输模式与隧道模式的深度解析及应用实例
随着网络安全威胁的日益严峻,IPsec作为网络层安全协议,其传输模式与隧道模式的选择对确保通信安全至关重要。本文旨在深入探讨这两种模式的差异,并通过实际案例展示其应用。 一、传输模式和隧道模式的详细描述 传输模式: 应用场景…...

实现Vue3/Nuxt3 预览excel文件
安装必要的库 npm install xlsx 创建一个组件来处理文件上传和解析: 在src/components 目录下创建一个名为 ExcelPreview.vue 的文件 <template> <div> <input type"file" change"handleFileUpload" /> <table v-if"…...

【AI落地应用实战】HivisionIDPhotos AI证件照制作实践指南
最近在网上发现了一款轻量级的AI证件照制作的项目,名为HivisionIDPhotos。它利用AI模型实现对多种拍照场景的识别、抠图与证件照生成,支持轻量级抠图、多种标准证件照和排版照生成、纯离线或端云推理、美颜等功能。此外,项目还提供了Gradio D…...

php实现sl651水文规约解析
SL651-2014-《水文监测数据通信规约》 1、要素解析说明 39 23 00 00 03 45 0x39查标识符得知为:39H Z 瞬时河道水位、潮位,我们定义为水位 0x23 按照要素标识符的规定,高5bit,低3bit,00100 011 对应的转换为10进制为4与3,也就是水位数据占用4字节,小…...

【Linux】简易版shell
文章目录 shell的基本框架PrintCommandLineGetCommandLineParseCommandLineExecuteCommandInitEnvCheckAndExecBuildCommand代码总览运行效果总结 shell的基本框架 要写一个命令行我们首先要写出基本框架。 打印命令行获取用户输入的命令分析命令执行命令 基本框架的代码&am…...

宝塔Linux面板安装PHP扩展失败报wget: unable to resolve host address ‘download.bt.cn’
一、问题: 当使用宝塔面板安装PHP扩展失败出现如下错误时 Resolving download.bt.cn(download.bt.cn)...failed: Connection timed out. wget: unable toresolve host address download.bt.cn’ 二、解决: 第一步:如下命令执行拿到返回的I…...

问:Redis常见性能问题及解法?
Redis 作为一个高性能的键值存储系统,在实际应用中可能会遇到各种性能问题。本文将探讨 Redis 的常见性能问题,并提供相应的解决建议。主要针对五个关键问题进行讨论:Master 节点的持久化工作、Slave 节点的数据备份、主从复制的网络环境、主…...

Imperva 数据库与安全解决方案
Imperva是网络安全解决方案的专业提供商,能够在云端和本地对业务关键数据和应用程序提供保护。公司成立于 2002 年,拥有稳定的发展和成功历史并于 2014 年实现产值1.64亿美元,公司的3700多位客户及300个合作伙伴分布于全球各地的90多个国家。…...

【JavaScript】之文档对象模型(DOM)详解
JavaScript 的强大之处在于它能够与 HTML 和 CSS 交互,动态地修改网页内容和样式。而实现这一功能的核心就是 DOM(文档对象模型)。 一、什么是 DOM? DOM 是文档对象模型(Document Object Model)的缩写。它…...

速盾:cdn域名与ip区别
CDN(内容分发网络)是一种通过在全球多个服务器上缓存和分发静态资源的网络服务,可以提高网站的访问速度和性能。在使用CDN时,域名与IP地址是两个关键的概念。本文将介绍CDN域名与IP地址的区别和作用。 首先,CDN域名是…...