Python使用asyncio包实现异步编程

2024-05-15 20:36

本文主要是介绍Python使用asyncio包实现异步编程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 异步编程

  异步编程是一种编程范式,用于处理程序中需要等待异步操作完成后才能继续执行的情况。异步编程允许程序在执行耗时的操作时不被阻塞,而是在等待操作完成时继续执行其他任务。这对于处理诸如文件 I/O、网络请求、定时器等需要等待的操作非常有用。
在这里插入图片描述
使用异步编程通常可以带来以下好处:

  • 提高程序效率和性能:异步编程使得程序在执行耗时的 I/O 操作(如网络请求、文件读写、数据库查询等)时不会被阻塞,减少了等待时间,充分利用了系统资源。
  • 改善用户体验:在 Web 开发中,异步编程可以确保服务器在处理大量并发请求时能够快速地响应用户,从而提高了 Web 应用的响应速度和用户体验。

2 async/await和asyncio包

2.1 异步函数的定义

  在Python中实现异步函数的定义需要两个关键字(asyncawait)。

  • asyncasync关键字声明一个异步函数。它可以在执行过程中暂停并允许其他代码执行。当你调用一个异步函数时,它会立即返回一个协程对象而不是实际的结果。异步函数适用于执行耗时的I/O操作,例如网络请求、文件读写、数据库查询等。这些操作通常涉及到等待外部资源的响应或者数据的传输,而在等待的过程中,CPU可以执行其他任务,从而提高程序的效率。
  • awaitawait关键字在 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()的计算,但多次执行上述程序的时候也出现了两个函数交替执行的结果。

参考资料

  1. https://cloud.tencent.com/developer/article/1795692

这篇关于Python使用asyncio包实现异步编程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/992852

相关文章

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本