对于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()的最后一句,所以到此完成了机器人获取发送语音指令到发送语音的过程。

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

相关文章
|
4月前
|
数据采集 关系型数据库 MySQL
python-协程(async、await关键字与asyncio)
python-协程(async、await关键字与asyncio)
82 0
|
3月前
|
Python
python tkinter Tcl_AsyncDelete: async handler deleted by the wrong thread
python tkinter Tcl_AsyncDelete: async handler deleted by the wrong thread
39 1
|
6天前
|
开发者 Python
探索Python中的异步编程:从回调到async/await
随着计算机系统的不断发展和多核处理器的普及,异步编程在Python中变得越来越重要。本文将深入探讨Python中异步编程的发展历程,从最初的回调函数到如今的async/await关键字,帮助读者更好地理解和应用异步编程技术。
|
4月前
|
Python
Python 的异步编程:什么是异步编程?Python 中的 `async` 和 `await` 关键字是用来做什么的?
Python 的异步编程:什么是异步编程?Python 中的 `async` 和 `await` 关键字是用来做什么的?
|
2月前
|
调度 Python
什么是Python中的协程(Coroutine)?如何使用`async`和`await`进行协程编程?
什么是Python中的协程(Coroutine)?如何使用`async`和`await`进行协程编程?
27 0
|
9月前
|
调度 Python
Python上篇:3. Python是如何从yield/send到yield from再到async/await
Python上篇:3. Python是如何从yield/send到yield from再到async/await
|
15天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
1天前
|
机器学习/深度学习 人工智能 数据可视化
Python:探索编程之美
Python:探索编程之美
9 0