对于python中async与await的理解

简介: 对于python中async与await的理解

       蓝多多在做QQ群机器人插件的时候遇到了async与await的使用,自己在百度上查了些资料,现在记录汇总一下。

目录

一、基本概念(源:协程和异步io - biu嘟 - 博客园):

二、进程、线程、协程的特点(源:异步、并发、协程原理 - 成都发哥 - 博客园):

三、async/await 使用

四、程序实例


一、基本概念(源:协程和异步io - biu嘟 - 博客园):

并发:指两个或多个事件在同一时间间隔内发生。是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机(CPU)上运行,但任一个时刻点上只有一个程序在处理机上运行。

并行:指两个或者多个事件在同一时刻发生,即是指任何时间点,有多个程序运行在多个CPU上。

同步:是指代码调用IO操作时,必须等待IO操作完成才能返回的调用方式。

异步:是指代码调用IO操作时,不必等待IO操作完成就能返回的调用方式。

协程:协程可以理解为纯用户态的线程,其通过协作而不是抢占来进行切换。相对于进程或者线程,协程所有的操作都可以在用户态完成,创建和切换的消耗更低。传统函数调用的过程为 A->B->C->D;我们需要一个可以暂停的函数,并且可以在适当的时候恢复该函数的继续执行,这便是协程,当程序中方法需要等待时间的话,就可以用协程。

二、进程、线程、协程的特点(源:异步、并发、协程原理 - 成都发哥 - 博客园):

进程(process):

       1、进程是资源分配的最小单位。

       2、进程间不共享内存,每个进程拥有自己独立的内存。

       3、进程间可以通过信号、信号量、共享内存、管道、队列等来通信。

       4、进程由操作系统调度。

线程(thread):

       1、线程是程序执行流的最小单位。

       2、线程是来自于进程的,一个进程下面可以开多个线程。

       3、每个线程都有自己一个栈,不共享栈,但多个线程能共享同一个属于进程的堆。

       4、线程因为是在同一个进程内的,可以共享内存。

       5、线程也是由操作系统调度,线程是 CPU 调度的最小单位。

       6、新开线程开销小于进程,CPU 在切换线程成本也小于进程。

       7、某个线程发生致命错误会导致整个进程崩溃。

协程(coroutine):

       1、对于操作系统来说只有进程和线程,协程的控制由应用程序显式调度,非抢占式。

       2、协程的执行最终靠的还是线程,应用程序来调度协程选择合适的线程来获取执行权。

       3、切换非常快,成本低,创建和切换的消耗更低。

三、async/await 使用

       函数在正常执行的过程中是不会发生中断的,所以如果需要写一个能够中断的函数,则需要添加async关键字。

       async 用来声明一个函数为异步函数,异步函数的特点是能在函数执行过程中挂起,去执行其他异步函数,等到挂起条件(例:挂起条件是sleep(1))消失后,也就是1秒到了再回来执行被挂起的函数。        

       await 用来用来声明程序挂起,比如异步程序执行到某一步时需要等待的时间很长,就将此挂起,去执行其他的异步程序。await 后面只能跟异步程序或有__await__属性的对象。

四、程序实例

1、机器人撤回含敏感词消息的函数

async def c(bot: Bot, event: GroupMessageEvent, state: T_State):
    mid = event.message_id
    print(mid)
    await bot.delete_msg(message_id=mid)

image.gif

       其中函数c采用async来声明为一个异步函数,函数c为异步函数;await声明了程序的挂起,后面跟随bot.delete_msg()这一异步函数,当执行到await bot.delete_msg(message_id=mid)这句代码时异步函数(程序)c挂起,去执行异步函数(程序)bot.delete_msg(),当挂起条件失效后,从异步函数bot.delete_msg()中跳出,继续执行原来函数(程序)c的操作。        

       通俗的来讲,设两个异步函数async def a(),async def b(),a函数中存在某一步具有有await关键字,当程序碰到关键字await b()后,异步程序a挂起,转去执行异步b程序,当挂起条件消失后,不论程序b是否执行完,都要从程序b中跳出,继续执行原程序原来的操作。 如果await后面跟的b函数不是异步函数,挂起条件不会消失,那么程序只能等函数b执行完再返回,无法在b执行的过程中返回。即与直接调用函数b相同,无需await关键字。在一个异步函数中,可以不止一次挂起,也就是可以用多个await。

2、博客园给出的代码实例:(源:对python async与await的理解 - xinghun85 - 博客园

import asyncio
import time
import requests
async def test2(i):
    r = await other_test(i)
    print(i, r)
async def other_test(i):
    r = requests.get(i)
    print(i)
    await asyncio.sleep(4)
    print(time.time() - start)
    return r
url = ["https://segmentfault.com/p/1210000013564725",
       "https://www.jianshu.com/p/83badc8028bd",
       "https://www.baidu.com/"]
loop = asyncio.get_event_loop()
task = [asyncio.ensure_future(test2(i)) for i in url]
start = time.time()
loop.run_until_complete(asyncio.wait(task))
endtime = time.time() - start
print(endtime)
loop.close()

image.gif

程序运行结果:

image.gif

可以自己根据程序的输出顺序来判断执行顺序,这里就不赘述了,感觉很清晰。

3、机器人发送语音函数分析(源:【qq机器人】机器人发语音_python菜鸟-CSDN博客

test = on_command('语音',rule=to_me(),priority=5)
@test.handle()
async def h_r(bot: Bot, event: Event, state: T_State):
    ms = await ma()
    chuo = f"[CQ:tts,text={ms}]"
    await test.send(Message(chuo))
async def ma():
    url = 'https://api.sunweihu.com/api/yan/api.php'
    resp = requests.get(url)
    return resp.text

image.gif

       当机器人收到@ +关键字“语音”时,会执行异步函数h_r(),执行到ms = await ma()语句时遇到await关键字,挂起程序h_r(),跳出并转入执行异步函数ma()进行声音的爬取操作,当挂起条件消失时(这里是爬取到音频后),完成函数ma()的执行,返回继续执行函数h_r(),当执行到await test.send(Message(chuo))语句时,又遇到await关键字,再次挂起程序h_r()转而执行消息发送程序test.send()致消息发送完毕,返回执行函数h_r(),因为 await test.send(Message(*))是函数h_r()的最后一句,所以到此完成了机器人获取发送语音指令到发送语音的过程。

个人理解,如有错误,欢迎评论区指正。谢谢

相关文章
|
14天前
|
数据库 Python
我们来看一个简单的Python协程示例,它使用了`async`和`await`关键字。
我们来看一个简单的Python协程示例,它使用了`async`和`await`关键字。
|
2月前
|
前端开发 Python
探索Python中的异步编程:从回调到async/await
本文将深入探讨Python中的异步编程模式,从最初的回调函数到现代的async/await语法。我们将介绍异步编程的基本概念,探讨其在Python中的实现方式,以及如何使用asyncio库和async/await语法来简化异步代码的编写。通过本文,读者将能够全面了解Python中的异步编程,并掌握使用异步技术构建高效、响应式应用程序的方法。
|
2月前
|
调度 UED Python
探索Python中的异步编程:从回调到async/await
本文将深入探讨Python中的异步编程,从最初的回调函数到现代的async/await语法。通过比较不同的异步编程方法,读者将了解它们的优缺点,并学习如何在项目中选择合适的方式来提高性能和可维护性。
|
2月前
|
开发者 Python
探索Python中的异步编程:从回调到async/await
随着计算机系统的不断发展和多核处理器的普及,异步编程在Python中变得越来越重要。本文将深入探讨Python中异步编程的发展历程,从最初的回调函数到如今的async/await关键字,帮助读者更好地理解和应用异步编程技术。
|
2月前
|
Python
Python 的异步编程:什么是异步编程?Python 中的 `async` 和 `await` 关键字是用来做什么的?
【4月更文挑战第14天】Python中的异步编程利用`async`和`await`关键字提升并发性能和响应速度。异步函数在等待操作时可暂停,协程是轻量级线程,实现任务间切换。示例展示了如何定义异步函数和协程,以及如何通过`asyncio`库并发执行任务。
21 1
|
2月前
|
开发者 Python
探索Python中的异步编程:从回调到async/await
传统的同步编程模式在处理I/O密集型任务时可能会面临性能瓶颈,因此异步编程成为了Python开发者的热门选择。本文将从回调函数的基本概念出发,探索Python中异步编程的发展历程,介绍了异步编程的核心概念和常见用法,最终深入讨论了Python 3.5引入的async/await关键字,以及它们如何简化异步代码的编写。
|
2月前
|
调度 Python
什么是Python中的协程(Coroutine)?如何使用`async`和`await`进行协程编程?
什么是Python中的协程(Coroutine)?如何使用`async`和`await`进行协程编程?
40 0
|
2天前
|
网络协议 开发者 Python
深度探索Python Socket编程:从理论到实践,进阶篇带你领略网络编程的魅力!
【7月更文挑战第25天】在网络编程中, Python Socket编程因灵活性强而广受青睐。本文采用问答形式深入探讨其进阶技巧。**问题一**: Socket编程基于TCP/IP,通过创建Socket对象实现通信,支持客户端和服务器间的数据交换。**问题二**: 提升并发处理能力的方法包括多线程(适用于I/O密集型任务)、多进程(绕过GIL限制)和异步IO(asyncio)。**问题三**: 提供了一个使用asyncio库实现的异步Socket服务器示例,展示如何接收及响应客户端消息。通过这些内容,希望能激发读者对网络编程的兴趣并引导进一步探索。
11 4
|
1天前
|
网络协议 Python
网络世界的建筑师:Python Socket编程基础与进阶,构建你的网络帝国!
【7月更文挑战第26天】在网络的数字宇宙中,Python Socket编程是开启网络世界大门的钥匙。本指南将引领你从基础到实战,成为网络世界的建筑师。
6 2