详细分析python中的 async 和 await(附Demo)

目录

  • 前言
  • 1. 基本知识
  • 2. Demo
    • 2.1 Demo1(同步)
    • 2.2 Demo2(错误)
    • 2.3 Demo3(不正确的异步)
    • 2.4 Demo4(正确异步)
  • 3. 完整版
  • 4. 拓展
    • 4.1 asyncio.create_task(coroutine)
    • 4.2 asyncio.gather(*coroutines_or_futures, return_exceptions=False)
    • 4.3 字符串拼接

前言

对于异步的基本知识推荐阅读我之前的文章:

  1. 详细讲解Python中的aioschedule定时任务操作
  2. java关于@Async异步调用详细解析附代码
  3. 【操作系统】线程与进程的深入剖析(全)
  4. 【操作系统】守护线程和守护进程的区别

1. 基本知识

在Python中,asyncawait是用于异步编程的关键字,引入了异步/协程(coroutine)的概念

异步编程是一种处理并发任务的方式,使得程序能够在等待某些I/O操作(如文件读写、网络请求等)的同时继续执行其他任务,而不会发生阻塞

  • 异步(Asynchronous):在异步编程中,程序不会等待某些I/O操作完成,而是继续执行其他任务,待操作完成后再回来处理结果
  • 协程(Coroutine):协程是一种轻量级的线程,可以在执行过程中暂停并让出控制权,然后在需要时恢复执行
    使用协程可以更有效地利用系统资源,避免线程切换的开销

作用:

  • 提高程序效率:异步编程可以充分利用I/O等待时间,使得程序在等待操作完成时能够继续执行其他任务,从而提高了整体程序的效率。
  • 改善用户体验:在网络编程中,异步操作可以避免阻塞用户界面,使得应用程序更加流畅。
  • 简化并发编程:通过使用async和await关键字,可以更方便地编写并发程序,避免了传统多线程编程中的锁和同步问题。

2. Demo

以下例子会一步步体现异步的重要性!

2.1 Demo1(同步)

为了比较异步,先给出同步的例子:

from time import sleep

def greet(name):
    print("Hello, " + name)
    sleep(2)  # 模拟一个耗时的操作
    print("Goodbye, " + name)


# 运行主函数
if __name__ == "__main__":
    greet("码农")
    greet("研究僧")

执行的顺序如下:
(这就是同步,需要等待上一个操作执行完)

在这里插入图片描述

2.2 Demo2(错误)

为了引入异步,我们先使用这个代码进行演示:(以下为错误代码)

from time import sleep

async def greet(name):
    print("Hello, " + name)
    sleep(2)  # 模拟一个耗时的操作
    print("Goodbye, " + name)

# 运行主函数
if __name__ == "__main__":
    greet("码农")
    greet("研究僧")

输出结果如下:

F:\python_project\test\main.py:19: RuntimeWarning: coroutine 'greet' was never awaited
  greet("码农")
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
F:\python_project\test\main.py:20: RuntimeWarning: coroutine 'greet' was never awaited
  greet("研究僧")
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

截图如下:

在这里插入图片描述

通过实战完善知识点:

在Python中,asyncawait是一对配合使用的关键字,用于定义异步函数和在异步函数中等待其他异步操作完成

配合使用可以实现协程的特性,使得异步编程更加简洁和易于理解

  • async关键字:
    async用于定义一个异步函数,表明该函数是一个协程,可以在其中使用await关键字等待其他异步操作完成
    异步函数的执行不会阻塞事件循环,而是会立即返回一个协程对象。

  • await关键字:
    await用于在异步函数内部等待其他协程执行完成,后面通常跟着一个需要等待的协程对象
    当遇到await关键字时,事件循环会挂起当前的协程,并执行其他任务,直到等待的协程完成后才会恢复执行当前协程

这两个关键字配合使用的好处在于:

  • 简化异步编程:使用asyncawait关键字可以使异步编程更加直观和易于理解,避免了回调函数和复杂的异步调度逻辑。

  • 实现协程asyncawait的组合使得函数可以在执行过程中暂停并恢复,实现了协程的特性,可以更灵活地处理异步任务。

  • 提高可读性:使用asyncawait可以使异步代码更加清晰和可读,使得程序逻辑更易于理解和维护。

2.3 Demo3(不正确的异步)

修正为如下:(正确)

import asyncio
from time import sleep


# 定义一个异步函数
async def greet(name):
    print("Hello, " + name)
    sleep(2)  # 模拟一个耗时的操作
    print("Goodbye, " + name)

async def main():
    await greet("码农")
    await greet("研究僧")

# 运行主函数
if __name__ == "__main__":
    asyncio.run(main())

或者

import asyncio

# 定义一个异步函数
async def greet(name):
    print("Hello, " + name)
    await asyncio.sleep(2)  # 模拟一个耗时的操作
    print("Goodbye, " + name)

async def main():
    await greet("码农")
    await greet("研究僧")

# 运行主函数
if __name__ == "__main__":
    asyncio.run(main())

这两者的输出都为如下:

在这里插入图片描述

光看上面的代码也只是同步输出,而不是异步输出的结果

2.4 Demo4(正确异步)

为了体现异步执行的效果,可以使用asyncio.create_task()创建任务并发执行

import asyncio

# 定义一个异步函数
async def greet(name):
    print("Hello, " + name)
    await asyncio.sleep(2)  # 使用异步的sleep函数
    print("Goodbye, " + name)

# 执行异步函数
async def main():
    # 创建任务并发执行
    task1 = asyncio.create_task(greet("码农"))
    task2 = asyncio.create_task(greet("研究僧"))

    # 等待所有任务完成
    await asyncio.gather(task1, task2)

# 运行主函数
if __name__ == "__main__":
    asyncio.run(main())

截图如下:

在这里插入图片描述

3. 完整版

完整版代码如下:

import asyncio
from datetime import datetime

# 定义一个异步函数
async def greet(name):
    print("Hello, " + name + str(datetime.now()))
    await asyncio.sleep(2)  # 使用异步的sleep函数
    print("Goodbye, " + name + str(datetime.now()))

# 执行异步函数
async def main():
    # 创建任务并发执行
    task1 = asyncio.create_task(greet("码农"))
    task2 = asyncio.create_task(greet("研究僧"))

    # 等待所有任务完成
    await asyncio.gather(task1, task2)

if __name__ == "__main__":
    start = datetime.now()  # 记录程序开始执行的时间
    asyncio.run(main())  # 运行主函数
    end = datetime.now()  # 记录程序结束执行的时间
    print('elapsed time =', end - start)  # 输出执行时间

输出结果如下:

在这里插入图片描述

4. 拓展

对于上述代码,有个别函数拓展如下

asyncio.create_task()asyncio.gather() 是 Python 中 asyncio 模块中的两个重要函数,用于创建和管理协程任务。都用于在异步编程中管理多个协程的执行,但是有着不同的作用和用法。

总的来说,asyncio.create_task() 用于并发执行多个协程任务,而 asyncio.gather() 用于等待多个协程任务的全部完成,并且可以收集执行结果
这两个函数是 asyncio 中协程任务管理的重要工具

4.1 asyncio.create_task(coroutine)

  • asyncio.create_task() 用于创建一个协程任务,并安排其立即执行
    接受一个协程对象作为参数,并返回一个任务对象
    该任务对象可以用来控制和管理该协程的执行,包括取消、等待其执行完成等
import asyncio

async def my_coroutine():
    await asyncio.sleep(1)
    print("Coroutine executed")

async def main():
    task = asyncio.create_task(my_coroutine())
    await task  # 等待任务执行完成

asyncio.run(main())

以上 使用 asyncio.create_task() 可以方便地并发执行多个协程

4.2 asyncio.gather(*coroutines_or_futures, return_exceptions=False)

  • asyncio.gather() 用于同时运行多个协程,并等待全部完成
    接受一系列的协程对象(或者 Future 对象)作为参数,并返回一个协程对象,该协程对象会在所有给定的协程都执行完毕后完成
import asyncio

async def coro1():
    await asyncio.sleep(1)
    return "Coroutine 1"

async def coro2():
    await asyncio.sleep(2)
    return "Coroutine 2"

async def main():
    result = await asyncio.gather(coro1(), coro2())
    print(result)

asyncio.run(main())

4.3 字符串拼接

对于输出函数来说,一般都由字符串组成
如果使用其他非字符串则需要进行转化

datetime.now()返回的是一个datetime对象,不能直接与字符串拼接
需要将datetime对象转换为字符串类型才能进行拼接

使用str()函数将datetime对象转换为字符串

print("Hello, " + name + ", 时间:" + str(datetime.now()))

或者使用字符串的format()方法进行格式化输出

print("Hello, {}, 时间: {}".format(name, datetime.now()))

或者使用 f-string 格式化字符串

print(f"Hello, {name}, 时间: {datetime.now()}")

这些都是将datetime.now()的结果转换为字符串后再与其他字符串进行拼接的方法

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FXTM富拓监管变更!2024开年连续3家交易商注销牌照

交易商的监管信息是经常发生变更的,即使第一次投资时查询平台监管牌照,投资者仍需持续关注其监管动态。千万不要以为第一步审核好后就万事大吉了! 2024年开年,就有3家交易商的重要信息发生变更,注销其金融监管牌照&…

Java 将TXT文本文件转换为PDF文件

与TXT文本文件,PDF文件更加专业也更适合传输,常用于正式报告、简历、合同等场合。项目中如果有使用Java将TXT文本文件转为PDF文件的需求,可以查看本文中介绍的免费实现方法。 免费Java PDF库 本文介绍的方法需要用到Free Spire.PDF for Java…

编程实例分享,宠物诊所电子处方怎么开,兽医电子处方模板电子版操作教程

编程实例分享,宠物诊所电子处方怎么开,兽医电子处方模板电子版操作教程 一、前言 以下操作教程以 佳易王兽医电子处方软件V16.0为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、在系统 设置里可以设置打印参数&#x…

《动手学深度学习(PyTorch版)》笔记7.2

注:书中对代码的讲解并不详细,本文对很多细节做了详细注释。另外,书上的源代码是在Jupyter Notebook上运行的,较为分散,本文将代码集中起来,并加以完善,全部用vscode在python 3.9.18下测试通过&…

单片机学习笔记---LED点阵屏的工作原理

目录 LED点阵屏分类 LED点阵屏显示原理 74HC595的介绍 一片74HC595的工作原理 多片级联工作原理 总结 LED点阵屏由若干个独立的LED组成,LED以矩阵的形式排列,以灯珠亮灭来显示文字、图片、视频等。LED点阵屏广泛应用于各种公共场合,如汽…

go语言进阶篇——面向对象(一)

什么是面向对象 在我们设计代码时,比如写一个算法题或者写一个问题结局办法时,我们常常会使用面向过程的方式来书写代码,面向过程主要指的是以解决问题为中心,按照一步步具体的步骤来编写代码或者调用函数,他在问题规…

后端创建订单

package com.java1234.entity;import io.jsonwebtoken.Claims;/*** jwt验证信息* author java1234_小锋* site www.java1234.com* company Java知识分享网* create 2019-08-13 上午 10:00*/ public class CheckResult {private int errCode;private boolean success;private Cl…

Linux下的多线程

前面学习了进程、文件等概念,接下里为大家引入线程的概念 多线程 线程是什么?为什么要有线程?线程的优缺点Linux线程操作线程创建线程等待线程终止线程分离 线程间的私有和共享数据理解线程库和线程id深刻理解Linux多线程(重点&a…

2023年全国职业院校技能大赛软件测试赛题第3套

2023年全国职业院校技能大赛 软件测试赛题第3套 赛项名称: 软件测试 英文名称: Software Testing 赛项编号: GZ034 归属产业: 电子与信息大类 …

软件价值10-数字时钟

这是一个数字时钟程序: # importing whole module from tkinter import * from tkinter.ttk import *# importing strftime function to # retrieve systems time from time import strftime# creating tkinter window root Tk() root.title(Clock)# This functio…

Docker Compose实例

目录 一、前提说明 二、简单的Docker容器部署案例 1. Dockerfile 配置 2. docker-compose.yml 配置 3. application.properties 配置 4. pom.xml 配置 5. 上传文件 6. 创建基础Docker镜像 7. docker-compose.yml编排 8. 停止并删除容器编排 一、前提说明 在配置好Do…

【博云2023】乘龙一跃腾云海,侧目抬手摘星河

癸卯渐远,甲辰渐至,预示着被汗水浇灌的种子,必将顶开冻土,迎接阳光。 每逢春节,当亲友彼此问候,博云人总能自豪地说,我们认真地、努力地奋斗,让我们能自信地踏上新的征程。 我们的…

使用Python进行数据的描述性分析,用少量的描述性指标来概括大量的原始数据

在进行数据分析时,当研究者得到的数据量很小时,可以通过直接观察原始数据来获得所有的信息。但是,当得到的数据量很大时,就必须借助各种描述性指标来完成对数据的描述工作。用少量的描述性指标来概括大量的原始数据,对…

用户和文件权限管理

一、用户管理 1、创建用户 [rootmaster ~]# useradd maple [rootmaster ~]# ll /home total 0 drwx------ 2 maple maple 62 Feb 7 20:47 maple drwx------ 2 www www 62 Jan 17 21:05 www [rootmaster ~]# passwd maple Changing password for user maple. New passwor…

Swift Combine 发布者publisher的生命周期 从入门到精通四

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二Swift Combine 管道 从入门到精通三 1. 发布者和订阅者的生命周期 订阅者和发布者以明确定义的顺序进行通信,因此使得它们具有从开始到结束的生命周期: …

深度学习系列56:使用whisper进行语音转文字

1. openai-whisper 这应该是最快的使用方式了。安装pip install -U openai-whisper,接着安装ffmpeg,随后就可以使用了。模型清单如下: 第一种方式,使用命令行: whisper japanese.wav --language Japanese --model…

12. BI - 可视化在项目蒸汽量预测的过程及应用

本文为 「茶桁的 AI 秘籍 - BI 篇 第 12 篇」 文章目录 工业蒸汽量预测 Hi, 你好。我是茶桁。 我们今天继续来看数据可视化做数据探索,今天我们还是来看相关项目。来看看可视化 EDA 在项目中的应用。 工业蒸汽量预测 接下来这个项目,是在阿里天池上的一…

c++之说_12|模板

关于模板&#xff0c;至少我们要先了解几个概念 一&#xff1a;函数模板 二&#xff1a;类模板 三&#xff1a;模板特化 四&#xff1a;形参参数包 模板覆盖的东西太多 我目前也不了解太多 函数模板 语法 template<typename 类型名,typename 类型名,typename ...多参…

006集——where语句进行属性筛选——arcgis

在arcgis中&#xff0c; dBASE 文件除了 WHERE 语句以外&#xff0c;不支持 其它 SQL 命令。选择窗口如下&#xff1a; 首先&#xff0c;我们了解下什么是where语句。 WHERE语句是SQL语言中使用频率很高的一种语句。它的作用是从数据库表中选择一些特定的记录行来进行操作。WHE…