Python异步编程之道:asyncio库的探索与应用

Python异步编程之道:asyncio库的探索与应用

一、引言

在Python编程中,异步编程是提高程序性能、处理高并发场景的重要技术。传统的同步编程模型在处理I/O密集型任务时,如网络请求、文件读写等,会导致CPU的空闲等待,从而降低程序的执行效率。而异步编程则允许程序在等待I/O操作完成时,继续执行其他任务,从而充分利用CPU资源,提高程序的并发性能。

Python的asyncio库是实现异步编程的重要工具,它提供了基于事件循环的并发模型,以及一系列高级API,使异步编程变得更加简单和高效。本文将深入探讨asyncio库的使用及其优势,并通过实例展示其在实际开发中的应用。

二、asyncio库概述

asyncio是Python 3.4版本引入的一个标准库,用于处理并发和异步编程。它提供了基于事件循环的并发模型,支持异步I/O、任务调度、协程等功能。asyncio库的主要组件包括事件循环、协程、任务、传输/协议等。

  • 事件循环:asyncio的核心组件,负责调度和执行任务,处理I/O操作以及响应系统事件。
  • 协程:可以暂停执行的函数,通过async def语法定义,使用await关键字等待异步操作完成。
  • 任务:协程的封装,表示一个正在运行或等待的协程。通过asyncio.create_task()asyncio.ensure_future()创建任务。
  • 传输/协议:用于实现底层网络通信的接口,如TCP、UDP等。

三、asyncio库的使用

asyncio库的使用主要围绕事件循环、协程和任务展开。下面将分别介绍它们的用法。

  1. 事件循环

事件循环是asyncio并发模型的核心组件。在使用asyncio时,通常需要获取一个事件循环实例,并调用其run_until_complete()run_forever()方法来启动事件循环。例如:

import asyncioasync def main():# 异步代码块pass# 获取事件循环实例并运行主协程
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

从Python 3.7开始,可以使用asyncio.run()函数来简化事件循环的启动和管理:

import asyncioasync def main():# 异步代码块pass# 使用asyncio.run()运行主协程
asyncio.run(main())
  1. 协程

协程是asyncio中实现异步编程的基本单元。使用async def语法定义协程函数,并在需要等待异步操作完成的地方使用await关键字。例如:

import asyncioasync def fetch_data(url):# 模拟网络请求print(f"Fetching {url}...")await asyncio.sleep(1)  # 假设网络请求耗时1秒return f"Data from {url}"async def main():# 并发发起多个网络请求tasks = [fetch_data('http://example.com/1'), fetch_data('http://example.com/2')]results = await asyncio.gather(*tasks)print(results)# 运行主协程
asyncio.run(main())

在上述示例中,我们定义了一个名为fetch_data()的协程函数,用于模拟网络请求。在main()协程中,我们并发地发起了两个网络请求,并使用await asyncio.gather(*tasks)等待它们完成。由于网络请求是I/O密集型操作,使用异步编程可以大大提高程序的并发性能。

  1. 任务

任务是协程的封装,表示一个正在运行或等待的协程。通过asyncio.create_task()asyncio.ensure_future()可以创建任务。例如:

import asyncioasync def fetch_data(url):# 模拟网络请求print(f"Fetching {url}...")await asyncio.sleep(1)return f"Data from {url}"async def main():# 创建任务并发起网络请求task1 = asyncio.create_task(fetch_data('http://example.com/1'))task2 = asyncio.create_task(fetch_data('http://example.com/2'))# 等待任务完成并获取结果result1 = await task1result2 = await task2print(result1, result2)# 运行主协程
asyncio.run(main())

在上述示例中,我们使用`asyncioPython异步编程之道:asyncio库的探索与应用

四、asyncio库的优势

asyncio库在Python异步编程中扮演着至关重要的角色,其优势主要体现在以下几个方面:

  1. 高效利用CPU资源:传统的同步编程模型在处理I/O密集型任务时,会导致CPU的空闲等待。而asyncio库通过异步编程模型,允许程序在等待I/O操作完成时,继续执行其他任务,从而充分利用CPU资源,提高程序的并发性能。
  2. 简洁易懂的编程模型:asyncio库引入了async/await语法,使得异步编程的编写变得更加简洁和直观。开发者可以使用类似于同步编程的代码风格来编写异步程序,降低了学习成本和开发难度。
  3. 丰富的API支持:asyncio库提供了丰富的API支持,包括协程、任务、传输/协议等,可以满足不同场景下的异步编程需求。同时,它还与Python的其他标准库(如socket、select等)和第三方库(如aiohttp、aiomysql等)进行了良好的集成,使得开发者可以更加便捷地实现异步网络通信和数据库操作等功能。
  4. 良好的扩展性:asyncio库基于事件循环的并发模型具有良好的扩展性。开发者可以自定义事件循环、协程、任务等组件,以满足特定场景下的需求。同时,asyncio库还支持与其他并发模型(如线程、进程等)进行集成,以实现更加复杂的并发编程任务。

五、asyncio库的应用实例

下面将通过一个简单的网络爬虫实例来展示asyncio库在实际开发中的应用。该实例使用aiohttp库发送HTTP请求,并使用asyncio库处理并发请求和响应。

首先,需要安装aiohttp库:

pip install aiohttp

然后,编写网络爬虫代码:

import asyncio
import aiohttpasync def fetch_page(session, url):async with session.get(url) as response:return await response.text()async def main(urls):async with aiohttp.ClientSession() as session:tasks = []for url in urls:task = asyncio.create_task(fetch_page(session, url))tasks.append(task)results = await asyncio.gather(*tasks)for index, result in enumerate(results):print(f"Page {index + 1} content:\n{result}\n")# 测试URL列表
urls = ['http://example.com/1', 'http://example.com/2', 'http://example.com/3']# 运行主协程
asyncio.run(main(urls))

在上述示例中,我们首先定义了一个名为fetch_page()的协程函数,用于发送HTTP请求并获取页面内容。然后,在main()协程中,我们使用aiohttp.ClientSession()创建一个会话对象,并并发地发起多个HTTP请求。最后,我们使用asyncio.gather()等待所有请求完成,并打印出每个页面的内容。

通过运行上述代码,我们可以看到asyncio库在处理并发网络请求时的优势。它允许我们同时发起多个请求,并在等待响应时继续执行其他任务,从而大大提高了程序的并发性能。

六、总结

本文深入探讨了Python中asyncio库的使用及其优势,并通过实例展示了其在异步编程中的应用。asyncio库通过引入事件循环、协程和任务等概念,使得异步编程变得更加简单和高效。同时,它还提供了丰富的API支持和良好的扩展性,使得开发者可以更加便捷地实现高性能的异步应用。对于追求高效率和优化性能的Python开发者而言,掌握asyncio库将是一个重要的技能。

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

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

相关文章

数据库出现死锁的解决方法参考

死锁引起的原因一般是多个用户并发访问数据库导致的问题,或是因为某个进程挂死以后资源未释放导致的。通过onstat –p可查看deadlks项大于0即表示历史总计死锁次数。对于被锁的表进行操作的时候会出现-143 ISAM error: deadlock detected的错误。当其他会话访问此表…

从JSON数据到Pandas DataFrame:如何解析出所需字段

目录 一、引言 二、JSON数据的基本结构 三、使用Pandas从JSON数据中读取数据 四、从DataFrame中解析出所需字段 解析对象字段 解析嵌套对象字段 解析数组字段 五、案例与代码示例 六、总结 一、引言 在数据分析和处理的日常工作中,我们经常需要从各种…

UBoat:一款功能强大的HTTP Botnet学习与研究工具

关于UBoat UBoat是一款功能强大的HTTP Botnet概念验证工具,该工具支持复刻一个现实场景中完整功能的Botnet测试环境,广大研究人员可以利用UBoat深入学习和研究Botnet的工作机制,以此来提升安全检测和保护策略。 功能介绍 1、基于C开发&…

luceda ipkiss教程 70:合并GDS版图

通过代码拼版: 所有代码如下: from si_fab import all as pdk from ipkiss3 import all as i3class Design1(i3.GDSCell):def _default_filename(self):return "Ring_Test.gds"def _default_name(self):return "Design1"class Des…

VTK官方例子

VTK官方例子 vtkMutableDirectedGraph #!/usr/bin/env python# noinspection PyUnresolvedReferences import vtkmodules.vtkInteractionStyle # noinspection PyUnresolvedReferences import vtkmodules.vtkRenderingOpenGL2 from vtkmodules.vtkCommonColor import vtkName…

EasyExcel自定义数据格式化

自定格式常量类 public class ExcelFormatConstants {public static final String DATE_FORMAT "yyyy-MM-dd";public static final String NUMBER_FORMAT_DEFAULT "#,##0.00";public static final String NUMBER_FORMAT_FOUR_DECIMAL "#,##0.0000…

Apache Flume事务

Apache Flume 中的事务处理是指 Flume Agent 在处理事件流时的一种机制,用于确保数据的可靠传输和处理。 1. 事务概述: Flume 中的事务是指一组事件的传输和处理,这些事件在传输过程中要么全部成功完成,要么全部失败&#xff0…

Jsp+Servlet实现图片上传和点击放大预览功能(提供Gitee源码)

前言:在最近老项目的开发中,需要做一个图片上传和点击放大的功能,在Vue和SpringBoot框架都有现成封装好的组件和工具类,对于一些上世纪的项目就没这么方便了,所以需要自己用原生的代码去编写,这里分享一下我…

01.Net基础知识

.Net的用途 Web、移动、云、桌面、游戏开发、物联网 (IDE:集成开发环境) .Net学习资源 Microsoft Learn、GitHub、G码云(Gitee) Visual Studio初步使用 1)可创建的项目种类(主要学习以下四…

JSON.parse()反序列化数据丢失

序列化:将数据转换为字符串的过程称为序列化。在序列化过程中,数据结构(比如对象、数组等)被转换成一个字符串形式,这个字符串通常以特定的格式表示,比如 JSON 或 XML。 反序列化:反序列化是序…

React Native跨平台开发实战:从零到一

最近在学习React Native跨平台开发,从零开始如何开发第一个基础应用并打包发布: 1. 环境准备 安装Node.js安装React Native CLI设置Android或iOS开发环境(取决于你想要支持的平台) 2. 创建新项目 使用React Native CLI创建一个…

Maven 的仓库、周期和插件

优质博文:IT-BLOG-CN 一、Maven 仓库 在Maven的世界中,任何一个依赖、插件或者项目构建的输出,都可以称为构建。Maven在某个统一的位置存储所有项目的共享的构建,这个统一的位置,我们就称之为仓库。任何的构建都有唯一…

经典权限五张表功能实现

文章目录 用户模块(未使用框架)查询功能实现步骤代码 新增功能实现步骤代码 修改功能实现步骤代码实现 删除功能实现步骤代码实现 用户模块会了,其他两个模块与其类似 用户模块(未使用框架) 查询功能 这里将模糊查询和分页查询写在一起 实现步骤 前端&#xff1…

翻译/润色找哪里比较专业,机构怎么选?

英文专业术语多,润色是很有必要的,大家可以选择专业的文章翻译润色服务,一定要挑选好正规的机构,这样的机构在出版过程中会为作者提供多项支持,对顺利发表是有帮助的。 科研领域英文论文专业润色包含这些内容&#xff…

基于Huffman编码的字符串统计及WPL计算

一、问题描述 问题概括: 给定一个字符串或文件,基于Huffman编码方法,实现以下功能: 1.统计每个字符的频率。 2.输出每个字符的Huffman编码。 3.计算并输出WPL(加权路径长度)。 这个问题要求对Huffman编码算…

德国Dürr杜尔机器人维修技巧分析

在工业生产中,杜尔工业机器人因其高效、精准和稳定性而备受青睐。然而,即便是最精良的设备,也难免会出现Drr机械手故障。 一、传感器故障 1. 视觉传感器故障:可能导致机器人无法正确识别目标物,影响工作效率。解决方法…

【页面】3D六边形

<!DOCTYPE html> <html> <head><title>3D正六边形</title><style>body {display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;}.container {perspective: 1000px;}.hexagon {width: 200px;height: 200px;…

ShellCode详解二

终于到了期待已久的编写代码环节了&#xff0c;哈哈哈哈~ 开始 首先&#xff0c;从上一章中我们了解到&#xff0c;shellcode代码是不可以包含任何的导入表的&#xff0c;所以我们写的所有shellcode代码都不可以调用系统库&#xff0c;这里说的不能调用是指不可以静态包含这些…

Server refused our key 【Navicat Premium 15 】

解决 Navicat Premium 15 SSH 连接报错 Server refused our key 1.1 问题描述 在使用 Navicat Premium 15 连接阿里云RDS数据库 Postgress 时&#xff0c;通过SSH隧道私钥连接报错 “Server refused our key”。 前提&#xff1a;目标服务器已经配置了本地生成的公钥 1.2 环…

Java并发处理

Java并发处理 问题描述:项目中业务编号出现重复编号 生成编号规则&#xff1a;获取数据库表最大值&#xff0c;然后再做1处理&#xff0c;即为新编号&#xff08;因为起始值是不固定的&#xff0c;还存在‘字符数据’格式&#xff0c;做了字典项可配置&#xff0c;所以不能直…