Python使用asyncio包实现异步编程
1. 异步编程
异步编程是一种编程范式,用于处理程序中需要等待异步操作完成后才能继续执行的情况。异步编程允许程序在执行耗时的操作时不被阻塞,而是在等待操作完成时继续执行其他任务。这对于处理诸如文件 I/O、网络请求、定时器等需要等待的操作非常有用。

使用异步编程通常可以带来以下好处:
- 提高程序效率和性能:异步编程使得程序在执行耗时的 I/O 操作(如网络请求、文件读写、数据库查询等)时不会被阻塞,减少了等待时间,充分利用了系统资源。
- 改善用户体验:在 Web 开发中,异步编程可以确保服务器在处理大量并发请求时能够快速地响应用户,从而提高了 Web 应用的响应速度和用户体验。
2 async/await和asyncio包
2.1 异步函数的定义
在Python中实现异步函数的定义需要两个关键字(async和await)。
async:async关键字声明一个异步函数。它可以在执行过程中暂停并允许其他代码执行。当你调用一个异步函数时,它会立即返回一个协程对象而不是实际的结果。异步函数适用于执行耗时的I/O操作,例如网络请求、文件读写、数据库查询等。这些操作通常涉及到等待外部资源的响应或者数据的传输,而在等待的过程中,CPU可以执行其他任务,从而提高程序的效率。await:await关键字在 Python 中用于等待一个异步操作完成。当调用异步函数时,使用await关键字可以暂时挂起当前的异步函数的执行,将CPU控制权还给事件循环(Event Loop)。接着事件循环可以将执行权转移到其他任务上,而不是一直等待当前的异步函数完成。当被await的异步操作完成后,事件循环会通知原来的异步函数,使得它可以继续执行后续的操作。
在Python中异步函数的定义需要同时满足以下两个条件:
- 使用
async def关键字声明函数。 - 函数内部包含异步操作,并且使用了
await关键字等待异步操作完成。如果一个函数中只使用了async def声明,但其中任何异步操作,也没有使用await关键字,那么它实际上就是一个普通的同步函数,而不是一个异步函数。
2.2 事件循环
事件循环(Event Loop)是异步编程中负责管理和调度异步任务执行的机制。事件循环的工作原理类似于一个持续运行的循环,它在每一轮循环中都会执行以下几个步骤:
- 等待任务就绪: 事件循环会等待所有注册的异步任务就绪,包括等待 I/O 操作完成、等待计时器超时等。
- 选择就绪任务:一旦有任务就绪,事件循环会选择其中一个任务进行执行。
- 执行任务:事件循环会执行所选择的就绪任务,直到任务完成或者遇到
await关键字,需要暂时挂起任务的执行。 - 挂起任务:如果任务遇到
await关键字,它会将控制权交还给事件循环,并等待await后面的异步操作完成。 - 继续执行其他任务:在等待
await的异步操作完成的过程中,事件循环会继续执行其他就绪的任务,从而实现了并发执行的效果。 - 异步操作完成: 当一个 await 后面的异步操作完成后,事件循环会通知原来的任务,使得它可以继续执行后续的操作。
2.2 asyncio包
asyncio包python中常用的异步编程框架,这里使用该框架完成一个简单的异步编程案例,具体如下:
import time
import datetime
import asyncio
async def async_read_file():print("async读文件开始:",datetime.datetime.fromtimestamp(time.time()))await asyncio.sleep(20)print("async读文件完成:",datetime.datetime.fromtimestamp(time.time()))def computer():print("普通计算密集型任务:",datetime.datetime.fromtimestamp(time.time()))sum=0for i in range(1000000):if i%250000==0 and i!=0:print("普通计算密集型任务正在执行:",datetime.datetime.fromtimestamp(time.time()))for j in range(500):sum+=i+j-2*jprint("普通计算密集型任务完成:",datetime.datetime.fromtimestamp(time.time()))def computer2():print("普通CPU密集型任务:",datetime.datetime.fromtimestamp(time.time()))sum=0for i in range(1000000):if i%250000==0 and i!=0:print("普通CPU密集型任务正在执行:",datetime.datetime.fromtimestamp(time.time()))for j in range(5000):sum+=i+j-2*jprint("普通CPU密集型任务完成:",datetime.datetime.fromtimestamp(time.time()))async def asy_main():task=loop.create_task(async_read_file()) # 创建一个任务,并添加到事件循环,等待执行task2=loop.run_in_executor(None,computer)# 将普通函数read_file添加到事件循环中,等待执行task3=loop.run_in_executor(None,computer2)# 将普通函数read_file2添加到事件循环中,等待执行await task3await task2await taskloop=asyncio.get_event_loop() # 创建一个事件循环
loop.run_until_complete(asy_main())
其执行结果如下:
普通计算密集型任务: 2024-05-15 18:29:19.702689
普通CPU密集型任务: 2024-05-15 18:29:19.708280
async读文件开始: 2024-05-15 18:29:19.738654
普通计算密集型任务正在执行: 2024-05-15 18:29:21.441072
普通计算密集型任务正在执行: 2024-05-15 18:29:23.192585
普通计算密集型任务正在执行: 2024-05-15 18:29:24.936979
普通计算密集型任务完成: 2024-05-15 18:29:26.712930
普通CPU密集型任务正在执行: 2024-05-15 18:29:32.539679
async读文件完成: 2024-05-15 18:29:39.752731
普通CPU密集型任务正在执行: 2024-05-15 18:29:41.813872
普通CPU密集型任务正在执行: 2024-05-15 18:29:51.103737
普通CPU密集型任务完成: 2024-05-15 18:30:00.433402
Tips:虽然当下的执行结果中写完成了computer()的计算,后完成了computer2()的计算,但多次执行上述程序的时候也出现了两个函数交替执行的结果。
参考资料
- https://cloud.tencent.com/developer/article/1795692
相关文章:
Python使用asyncio包实现异步编程
1. 异步编程 异步编程是一种编程范式,用于处理程序中需要等待异步操作完成后才能继续执行的情况。异步编程允许程序在执行耗时的操作时不被阻塞,而是在等待操作完成时继续执行其他任务。这对于处理诸如文件 I/O、网络请求、定时器等需要等待的操作非常有…...
获取文件夹下的vue文件形成组件,require.context
前言:项目中现有一个文件里面包含所有需要用到的组件,如果一个个的去import,则会非常麻烦,现有require.context去实现, 1、require.context var request require.context(‘./module’, true, /.js$/) require.cont…...
2024软件测试必问的常见面试题1000问!
01、您所熟悉的测试用例设计方法都有哪些?请分别以具体的例子来说明这些方法在测试用例设计工作中的应用。 答:有黑盒和白盒两种测试种类,黑盒有等价类划分法,边界分析法,因果图法和错误猜测法。白盒有逻辑覆盖法&…...
C++列表实现
文章目录 一、listView相关内容主要思想实例全部代码 二、QTreeView 一、listView 相关内容 QAbstractItemModel:一个抽象的类,为数据项模型提供抽象的接口,常见的的数据模型列如:QStringListModel,QStandardItemMode,QDirModel…...
论文合集整理推荐2024.5.15
2012年论文合集:论文入口 2019年论文合集:论文入口 2022年论文合集:论文入口 2023年论文合集:论文入口 2024年论文合集:论文入口...
JavaScript的跳转传参方式
在JavaScript中,页面跳转并传递参数通常可以通过几种不同的方式来实现。下面是一些常见的方法: 1.URL参数(Query String) 这是最常见的方式,通过在URL的末尾添加参数来实现。例如: javascriptwindow.loc…...
非阻塞模式下的读写操作
实现文件IO的非阻塞模式的读写操作 fcntl函数 功能: #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ ); // arg表示可变参数,由cmd决定 fcntl()对打开的文件描述符fd执行下面描述的操作之一。操作由cmd决…...
Google Ads谷歌广告账户被封停怎么办?
跨境出海业务少不了需要做Google Ads推广业务;其中让投手们闻风丧胆的消息就是帐户被暂停。当 Google 检测到任何违反其政策且可能损害用户在线体验的行为时,就会发生这种情况。那么如何在做广告推广的同时,保证账号不被封禁呢?看…...
AI大模型探索之路-训练篇23:ChatGLM3微调实战-基于P-Tuning V2技术的实践指南
系列篇章💥 AI大模型探索之路-训练篇1:大语言模型微调基础认知 AI大模型探索之路-训练篇2:大语言模型预训练基础认知 AI大模型探索之路-训练篇3:大语言模型全景解读 AI大模型探索之路-训练篇4:大语言模型训练数据集概…...
掌握核心概念:Java高级面试难题精解(一)
Java 高级面试问题及答案 问题1: 在Java中,什么是泛型擦除?为什么需要它? 答案: 泛型擦除是Java编译器的一个特性,它在运行时移除泛型类型信息,以确保类型安全。Java的泛型是在J2SE 1.5中引入的ÿ…...
Nagle算法
Nagle算法简介 Nagle算法主要是避免发送小的数据包,要求TCP连接上最多只能有一个未被确认的小分组,在该分组的确认到达之前不能发送其他的小分组。 在默认的情况下,Nagle算法是默认开启的,Nagle算法比较适用于发送方发送大批量的小数据&…...
MPLS小实验
实验图: 实验要求: 要求使用MPLS技术,将实验通,并在实验结束后使用命令:tracert -v -a 看是否基于标签进行转发。 如上:在每台路由器上都有两个环回,一个用于模拟用户网段,一个用于M…...
MongoDB聚合运算符:$week
MongoDB聚合运算符:$week 文章目录 MongoDB聚合运算符:$week语法使用举例 $week聚合运算符返回指定日期日期为一年中第几周的数字值为0到53之间。周从周日开始,第1周从一年的第一个周日开始。一年中第一个星期日之前的日期为第0周。这和 str…...
【Linux】如何定位客户端程序的问题
文章目录 1 客户端程序和服务端程序的差别2 问题类型2.1 崩溃(crash)2.2 CPU高2.3 内存高2.4 线程卡死 3 总结 1 客户端程序和服务端程序的差别 客户端程序是运行在终端上,通常都会与业务系统共存,而服务端程序通常会运行在单独的节点上,或者…...
AI学习指南数学工具篇-PCA基础知识
AI学习指南数学工具篇-PCA基础知识 1. PCA是什么? PCA,即主成分分析(Principal Component Analysis),是一种常用的数据降维技术。它通过线性变换将原始数据投影到一个新的坐标系中,旨在找到数据中的“主成…...
《系统架构设计师教程(第2版)》第4章-信息安全技术基础知识-02-信息加密技术
文章目录 1. 信息加密技术1.1 数据加密1.2 对称密钥加密算法1)数据加密标准(DES)2)三重DES(Triple-DES)3)国际数据加密算法(IDEA)4)高级加密标准(AES…...
Leetcode 404:左叶子之和
给定二叉树的根节点 root ,返回所有左叶子之和。 思路:遍历树,寻找左叶子节点; 如果判断是左叶子节点,就更新sum。 public static int sumOfLeftLeaves(TreeNode root){int sum0;sumcompute(root,sum);return sum;}/…...
Keil问题解决:结构体数组初始化,初始化后的值不是目标值
省流:使用的编译器为compiler version 6,切换为compiler version 5 如果缺少编译器,请参考:Keil手动安装编译器V5版本 结构体定义: typedef struct _TASK_COMPONENTS {uint8_t Run; // 程序运行标…...
C++set关联式容器
Cset 1. 关联式容器 vector、list、deque、forward_list(C11)等STL容器,其底层为线性序列的数据结构,里面存储的是元素本身,这样的容器被统称为序列式容器。而map、set是一种关联式容器,关联式容器也是用来存储数据的࿰…...
Celery Redis 集群版连接和PyCharm启动配置
目录 使用Redis cluster版作为broker原因 PyCharm配置 使用Redis cluster版作为broker 在celery5及其之前版本,需要配置如下才可行 celery_app.conf.update( broker_transport_options{“global_keyprefix”: “{celery}:”}, ) 原因 https://github.com/celery/…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...
Spring AOP代理对象生成原理
代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】,这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...
聚六亚甲基单胍盐酸盐市场深度解析:现状、挑战与机遇
根据 QYResearch 发布的市场报告显示,全球市场规模预计在 2031 年达到 9848 万美元,2025 - 2031 年期间年复合增长率(CAGR)为 3.7%。在竞争格局上,市场集中度较高,2024 年全球前十强厂商占据约 74.0% 的市场…...
Win系统权限提升篇UAC绕过DLL劫持未引号路径可控服务全检项目
应用场景: 1、常规某个机器被钓鱼后门攻击后,我们需要做更高权限操作或权限维持等。 2、内网域中某个机器被钓鱼后门攻击后,我们需要对后续内网域做安全测试。 #Win10&11-BypassUAC自动提权-MSF&UACME 为了远程执行目标的exe或者b…...
AWSLambda之设置时区
目标 希望Lambda运行的时区是东八区。 解决 只需要设置lambda的环境变量TZ为东八区时区即可,即Asia/Shanghai。 参考 使用 Lambda 环境变量...
