当前位置: 首页 > article >正文

深入探索 Python 中的 asyncio:异步编程的利器

在当今的软件开发中,异步编程已经成为了提高程序性能和响应能力的重要手段之一。Python 作为一种广泛使用的编程语言,提供了强大的异步编程支持,而 asyncio 库则是其中的核心。本文将深入探讨 asyncio 的基本概念、使用方法以及一些高级特性,帮助读者更好地理解和应用异步编程。
一、异步编程简介
在传统的同步编程中,程序的执行是顺序的,一个任务完成后才会开始下一个任务。如果某个任务需要等待(例如 I/O 操作),整个程序就会被阻塞,直到该任务完成。这种模式在处理 I/O 密集型任务时效率低下,因为 CPU 在等待 I/O 的过程中处于空闲状态。
异步编程则允许程序在等待某个任务完成时,切换到其他任务的执行,从而充分利用 CPU 的计算能力。Python 中的 asyncio 库就是为异步编程而设计的,它提供了一种基于事件循环的编程模型,使得程序可以在等待 I/O 操作时执行其他任务。
二、asyncio 的基本概念
1. 事件循环(Event Loop)
事件循环是 asyncio 的核心,它负责调度和管理异步任务。事件循环会不断地检查是否有任务可以执行,如果有,则将其放入执行队列中;如果没有,则等待某个任务完成。事件循环的运行是异步编程的基础。
在 Python 中,可以通过以下代码获取默认的事件循环:

import asyncioloop = asyncio.get_event_loop()

2. 协程(Coroutine)
协程是异步编程中的基本单元,它是一种特殊的函数,可以通过 async 关键字定义。协程可以被暂停和恢复,这使得它可以在等待 I/O 操作时释放控制权,让其他任务可以执行。
以下是一个简单的协程示例:

async def hello():print("Hello")await asyncio.sleep(1)print("World")

3. 任务(Task)
任务是协程的封装,它将协程与事件循环联系起来。事件循环可以通过任务来调度协程的执行。可以通过以下代码将协程转换为任务:

task = loop.create_task(hello())

或者使用 asyncio.create_task() 函数:

task = asyncio.create_task(hello())

三、asyncio 的基本使用
1. 运行协程
要运行协程,需要将其转换为任务,并将其加入事件循环。以下是一个完整的示例:

import asyncioasync def hello():print("Hello")await asyncio.sleep(1)print("World")async def main():task1 = asyncio.create_task(hello())task2 = asyncio.create_task(hello())await task1await task2loop = asyncio.get_event_loop()
loop.run_until_complete(main())

在这个例子中,main 函数创建了两个任务 task1 和 task2,并将它们加入事件循环。await task1 和 await task2 表示等待这两个任务完成。
2. 并发执行
asyncio 支持并发执行多个任务。在上面的例子中,task1 和 task2 是并发执行的,它们的执行顺序是不确定的。这是因为事件循环会根据任务的状态来调度它们的执行。
3. 异步 I/O 操作
asyncio 提供了许多异步 I/O 操作的接口,例如 asyncio.open_connection()、asyncio.start_server() 等。这些接口可以用于异步地进行网络通信、文件操作等。
以下是一个异步网络请求的示例:

import asyncio
import aiohttpasync def fetch(session, url):async with session.get(url) as response:return await response.text()async def main():async with aiohttp.ClientSession() as session:html = await fetch(session, 'http://example.com')print(html)loop = asyncio.get_event_loop()
loop.run_until_complete(main())

在这个例子中,fetch 函数使用 aiohttp 库异步地发送 HTTP 请求,并返回响应的内容。main 函数创建了一个 aiohttp.ClientSession 对象,并调用 fetch 函数获取网页内容。
四、asyncio 的高级特性
1. 锁(Lock)
在并发编程中,锁是一种常用的同步机制。asyncio 提供了 asyncio.Lock 类,用于在协程之间同步访问共享资源。
以下是一个使用锁的示例:

import asyncioasync def worker(lock, num):async with lock:print(f"Worker {num} is working")await asyncio.sleep(1)print(f"Worker {num} finished")async def main():lock = asyncio.Lock()tasks = [asyncio.create_task(worker(lock, i)) for i in range(5)]await asyncio.gather(*tasks)loop = asyncio.get_event_loop()
loop.run_until_complete(main())

在这个例子中,worker 函数使用 async with lock 语句获取锁,只有当锁被释放后,其他协程才能获取锁并执行。
2. 信号量(Semaphore)
信号量是一种比锁更灵活的同步机制,它可以控制同时访问共享资源的协程数量。asyncio 提供了 asyncio.Semaphore 类,用于实现信号量。
以下是一个使用信号量的示例:

import asyncioasync def worker(semaphore, num):async with semaphore:print(f"Worker {num} is working")await asyncio.sleep(1)print(f"Worker {num} finished")async def main():semaphore = asyncio.Semaphore(2)tasks = [asyncio.create_task(worker(semaphore, i)) for i in range(5)]await asyncio.gather(*tasks)loop = asyncio.get_event_loop()
loop.run_until_complete(main())

在这个例子中,semaphore 的值为 2,表示最多允许 2 个协程同时访问共享资源。当有超过 2 个协程请求访问时,其他协程会被阻塞,直到有协程释放信号量。
3. 条件变量(Condition)
条件变量是一种用于协程之间通信的机制,它允许协程在满足某个条件时进行通知和等待。asyncio 提供了 asyncio.Condition 类,用于实现条件变量。
以下是一个使用条件变量的示例:

import asyncioasync def consumer(condition):async with condition:print("Consumer is waiting")await condition.wait()print("Consumer is notified")async def producer(condition):async with condition:print("Producer is producing")await asyncio.sleep(1)print("Producer is notifying")condition.notify_all()async def main():condition = asyncio.Condition()consumer_task = asyncio.create_task(consumer(condition))producer_task = asyncio.create_task(producer(condition))await consumer_taskawait producer_taskloop = asyncio.get_event_loop()
loop.run_until_complete(main())

在这个例子中,consumer 函数使用 await condition.wait() 语句等待条件变量的通知,producer 函数使用 condition.notify_all() 语句通知所有等待的协程。
五、总结
asyncio 是 Python 中强大的异步编程库,它提供了事件循环、协程、任务等基本概念,以及锁、信号量、条件变量等高级特性。通过使用 asyncio,可以实现高效的异步编程,提高程序的性能和响应能力。希望本文能够帮助读者更好地理解和应用 asyncio,在实际开发中发挥其优势。
----
希望这篇文章对你有帮助!如果你有其他主题或需求,欢迎随时告诉我。

相关文章:

深入探索 Python 中的 asyncio:异步编程的利器

在当今的软件开发中,异步编程已经成为了提高程序性能和响应能力的重要手段之一。Python 作为一种广泛使用的编程语言,提供了强大的异步编程支持,而 asyncio 库则是其中的核心。本文将深入探讨 asyncio 的基本概念、使用方法以及一些高级特性&…...

STM32硬件IIC与OLED使用

OLED屏幕介绍 OLED即有机发光管(Organic Light-Emitting Diode,OLED)。OLED显示技术具有自发光、广视角、几乎无穷高的对比度、较低功耗、极高反应速度、可用于绕曲性面板、使用温度范围广、构造及制程简单等有点,被认为是下一代的平面显示屏新兴应用技术 OLED显示…...

基于Spring Boot的电动车智能充电服务平台的设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...

十、JavaScript对象

一、对象 创建对象的方法有三种:字面量、new、构造函数。 1.利用字面量创建对象 花括号{}里面包含了表达这个具体事物(对象)的属性和方法 // 1.利用对象字面量创建对象{}// var obj {}; // 创建了一个空的对象var obj {uname: black,ag…...

FFmpeg开发学习:音视频封装

1.基本流程 1.输入参数 输出文件路径 char *output 视频编码参数 AVCodecParameters *video_par 音频编码参数 AVCodecParameters *audio_par 数据包 AVPacket *packets[] 2.封装流程 (1)创建输出的上下文AVFormatContext指针 AVFormatContext *out_fm…...

hackmyvm-reversteg

arp-scan -l nmap -sS -v 192.168.222.45 在源码中可以看到 根据下面的提示可以猜测117db0148dc179a2c2245c5a30e63ab0是一个图像文件 将图片下载到本地 隐写术 在两张图片上使用strings,发现有一些可打印的字符串 strings 117db0148dc179a2c2245c5a30e63ab0.jpg base64解码…...

UE4学习笔记 FPS游戏制作17 让机器人持枪 销毁机器人时也销毁机器人的枪 让机器人射击

添加武器插槽 打开机器人的Idle动画,方便查看武器位置 在动画面板里打开骨骼树,找到右手的武器节点,右键添加一个插槽,重命名为RightWeapon,右键插槽,添加一个预览资产,选择Rifle,根…...

考研408-数据结构完整代码 线性表的链式存储结构 - 单链表

单链表操作详解&#xff08;C实现&#xff09; 目录 单链表尾插法创建单链表头插法创建删除指定节点按值查找按序号查找插入节点完整代码示例注意事项总结 尾插法创建 #include<bits/stdc.h> using namespace std;typedef struct LNode {int data;struct LNode* next;…...

蓝桥杯经典题解:班级活动分组问题的深度解析与优化实现

目录 一、问题背景与描述 二、问题分析与核心思路 2.1 问题本质&#xff1a;统计与配对优化 2.2 关键观察 2.3 数学建模 三、算法设计与实现步骤 3.1 算法步骤 3.2 代码实现&#xff08;Python&#xff09; 3.3 优化点分析 四、关键细节与常见误区 4.1 细节处理 4.…...

设计模式(创建型)-建造者模式

定义 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它将一个复杂对象的构建与它的表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。该模式允许通过多个简单的步骤逐步构建出一个复杂的对象&#xff0c;用户只需指定复杂对象…...

RIP和OSPF的区别

文章目录 RIP&#xff08;路由信息协议&#xff09;和 OSPF&#xff08;开放最短路径优先&#xff09;是两种常见的动态路由协议&#xff0c;它们的主要区别如下&#xff1a;1. 协议类型2. 更新方式3. 路由计算算法4. 最大跳数5. 管理距离&#xff08;AD&#xff09;6. 认证机制…...

Git 之配置ssh

1、打开 Git Bash 终端 2、设置用户名 git config --global user.name tom3、生成公钥 ssh-keygen -t rsa4、查看公钥 cat ~/.ssh/id_rsa.pub5、将查看到的公钥添加到不同Git平台 6、验证ssh远程连接git仓库 ssh -T gitgitee.com ssh -T gitcodeup.aliyun.com...

遍历数组时,如何获取数组每个元素索引号

在 JavaScript 中&#xff0c;有多种方法可以在遍历数组时获取每个元素的索引号&#xff0c;下面为你介绍几种常用的方法&#xff1a; 1. 使用 for 循环 const array [apple, banana, cherry]; for (let i 0; i < array.length; i) {console.log(索引 ${i} 的元素是: ${…...

黑马点评项目

遇到问题&#xff1a; 登录流程 session->JWT->SpringSession->tokenRedis &#xff08;不需要改进为SpringSession&#xff0c;token更广泛&#xff0c;移动端或者前后端分离都可以用&#xff09; SpringSession配置为redis模式后&#xff0c;redis相当于分布式se…...

如何防御TCP洪泛攻击

TCP洪泛攻击&#xff08;TCP Flood Attack&#xff09;是一种常见的分布式拒绝服务&#xff08;DDoS&#xff09;攻击手段&#xff0c;以下是其原理、攻击方式和危害的详细介绍&#xff1a; 定义与原理 TCP洪泛攻击利用了TCP协议的三次握手过程。在正常的TCP连接建立过程中&a…...

【AVRCP】AVRCP核心术语解析

目录 一、协议核心术语&#xff1a;架构的基石 1.1 音视频控制协议簇&#xff08;AVRCP 生态链&#xff09; 1.2 数据传输协议&#xff08;L2CAP 核心术语&#xff09; 二、设备架构术语&#xff1a;角色与交互 2.1 设备角色模型&#xff08;CT/TG 二元架构&#xff09; …...

【弹性计算】异构计算云服务和 AI 加速器(四):FPGA 虚拟化技术

异构计算云服务和 AI 加速器&#xff08;四&#xff09;&#xff1a;FPGA 虚拟化技术 &#x1f680; FPGA&#xff08;Field-Programmable Gate Array&#xff0c;现场可编程门阵列&#xff09;是一种可重构的半导体芯片&#xff0c;允许用户根据需要动态配置硬件逻辑&#xff…...

Python爬虫如何检测请求频率?

在进行网络爬虫开发时&#xff0c;合理设置请求频率是确保爬虫稳定运行、避免被目标网站封禁的关键策略之一。以下是一些有效的方法和最佳实践&#xff0c;帮助你合理设置请求频率&#xff0c;确保爬虫的可持续性和稳定性。 一、了解速度限制的原因 网站对爬虫速度进行限制的…...

编译原理——自底向上语法优先分析

文章目录 自底向上优先分析概述一、自底向上优先分析概述二、简单优先分析法&#xff08;一&#xff09;优先关系定义&#xff08;二&#xff09;简单优先文法的定义&#xff08;三&#xff09;简单优先分析法的操作步骤 三、算法优先分析法&#xff08;一&#xff09;直观算符…...

nuxt3网站文章分享微信 ,QQ功能

1.安装 npm install qrcode --save-dev 2.组件使用 <div class"share"><div style"line-height: 69px; color: #fff;width: 100px;"><p style"text-align: center;">分享:</p></div><div click"shareToMi…...

智能任务分配:Python高并发架构设计

Python并发编程实战&#xff1a;多进程与多线程的智能任务分配策略 引言&#xff1a;突破性能瓶颈的关键选择 在CPU核心数量激增和I/O密集型应用普及的今天&#xff0c;Python开发者面临着一个关键抉择&#xff1a;如何通过并发编程充分释放硬件潜力&#xff1f;本文通过实测数…...

Oracle 数据库通过exp/imp工具迁移指定数据表

项目需求&#xff1a;从prod数据库迁移和复制2个表(BANK_STATE&#xff0c;HBS)的数据到uat数据库环境。 数据库版本&#xff1a;Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 迁移工具&#xff1a;客户端exp/imp工具 -- 执行命令 从Prod数据库导出数据exp us…...

批发订货系统:驱动企业数字化转型的核心引擎

在数字经济时代&#xff0c;传统批发企业正面临供应链效率低、客户体验不足、管理成本高等挑战。而批发订货系统作为企业数字化转型的重要工具&#xff0c;正通过智能化、数据化和流程重构&#xff0c;重塑企业的运营模式&#xff0c;助力企业实现降本增效与业务创新。以下从多…...

STM32F103_LL库+寄存器学习笔记07 - 串口接收缓冲区非空中断

导言 上一章节《STM32F103_LL库寄存器学习笔记06 - 梳理串口与串行发送“Hello,World"》梳理完USART的基本设置与发送字符串“Hello,World"&#xff0c;接着梳理接收缓冲区非空中断。 实用的串口接收程序都会使用中断方式&#xff0c;不会使用轮询方式。最主要的原因…...

python将整个txt文件写入excel的一个单元格?

要将整个txt文件写入Excel的一个单元格&#xff0c;可以使用Python的openpyxl库来实现。以下是一个简单的示例代码&#xff1a; from openpyxl import Workbook# 读取txt文件内容 with open(file.txt, r) as file:txt_content file.read()# 创建一个新的Excel工作簿 wb Work…...

CentOS 8 Stream 配置在线yum源参考 —— 筑梦之路

CentOS 8 Stream ISO 文件下载地址&#xff1a;http://mirrors.aliyun.com/centos-vault/8-stream/isos/x86_64/CentOS-Stream-8-20240603.0-x86_64-dvd1.isoCentOS 8 Stream 网络引导ISO 文件下载地址&#xff1a;http://mirrors.aliyun.com/centos-vault/8-stream/isos/x86_6…...

生物中心论

Robert Lanza的“生物中心论”&#xff08;Biocentrism&#xff09;是一种以生命和意识为核心的宇宙观&#xff0c;试图颠覆传统科学对时间、空间和物质的理解。 一、核心观点 意识创造宇宙 生物中心论认为&#xff0c;宇宙的存在依赖于观察者的意识。传统科学将宇宙视为独立实…...

LeetCode //C - 650. 2 Keys Keyboard

650. 2 Keys Keyboard There is only one character ‘A’ on the screen of a notepad. You can perform one of two operations on this notepad for each step: Copy All: You can copy all the characters present on the screen (a partial copy is not allowed).Paste:…...

【leetcode hot 100 347】前 K 个高频元素

解法一&#xff1a;用map的value记录key出现的次数&#xff0c;用PriorityQueue构造最小堆。 class Solution {public int[] topKFrequent(int[] nums, int k) {// 把元素放在map中Map<Integer,Integer> map new HashMap<>();for(int num:nums){if(map.containsK…...

Spring三级缓存解决循环依赖的深度解析

一、循环依赖场景 假设存在两个Bean的相互依赖&#xff1a; Component public class ServiceA {Autowiredprivate ServiceB serviceB; }Component public class ServiceB {Autowiredprivate ServiceA serviceA; }二、三级缓存定义 在 DefaultSingletonBeanRegistry 中定义&a…...