欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > python >内容正文

python

python中重要的模块asyncio

发布时间:2025/3/21 python 37 豆豆
生活随笔 收集整理的这篇文章主要介绍了 python中重要的模块asyncio 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

生活中,假设 你是一家制造汽车的老板,员工点击设备的【开始】按钮之后,在设备前需等待30分钟,然后点击【结束】按钮,此时作为老板的你一定希望这个员工在等待的那30分钟的时间去做点其他的工作。

模块asyncio用于编写协程代码,下面利用代码来还原生活中的例子。

定义一个协程

协程(Coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术。简而言之,其实就是通过一个线程实现代码块相互切换执行。
形式为: async def的函数。使用async修饰将普通函数包装成异步函数,直接调用异步函数不会返回结果,而是返回一个协程(coroutine)对象;

# 定义一个协程函数 async def request():print('***')return 123coroutine = request() #调用协程函数函数内部代码不会执行,只是返回一个协程对象 print(coroutine) #<coroutine object request at 0x7fc0a515cdc0>

事件循环

协程对象不能直接运行,需要将协程加入到事件循环loop中。

创建一个事件循环loop

在主线程里,如果没有被设置过任何事件循环,那么调用asyncio.get_event_loop()会创建一个事件循环并返回;
其他线程里需要首先loop=new_event_loop(),然后set_event_loop(loop).

loop = asyncio.get_event_loop() #创建一个事件循环 print('Task:', task)#进入事件循环 Task: <Task pending name='Task-1' coro=<request() running at /Users/demo.py>>

将协程注册到事件循环,并启动事件循环

调用loop.run_until_complete(task)将协程加入到事件循环loop中,并启动事件循环,直到协程(task)执行完成之后终止
在注册事件循环的时候,run_until_complete(task)方法需要一个任务(task)对象,task对象是Future类的子类,保存了协程运行后的状态,用于未来获取协程的结果。

创建一个task

task = asyncio.ensure_future(coroutine) #创建task print('Task:', task) #Task: <Task pending name='Task-1' coro=<request() running at /Users/demo.py>>loop.run_until_complete(task) #将协程当做任务提交到事件循环的任务列表中,协程执行完成之后终止 print('Task:', task)#关闭事件循环 *** Task: <Task finished name='Task-1' coro=<request() done, defined at /Users/demo.py> 123

可以通过asyncio.ensure_future(coroutine) 创建task,也可以通过loop.create_task(coroutine)创建task。
asyncio.ensure_future(coroutine):将一个coroutine对象包装成Future对象

**Future对象:**状态:Pending、Running、Done、Cacelled;
创建future的时候,task为pending,
事件循环调用执行的时候当然就是running,
调用完毕自然就是done,
如果需要停止事件循环,中途需要取消,就需要先把task取消,即为cancelled。

绑定回调

在task执行完成的时候可以获取执行的结果,回调函数的最后一个参数是future对象,通过该对象可以获取协程返回值。

def callback(future):print('Status:', future.result()) #获取协程返回值task = asyncio.ensure_future(coroutine) #创建task print('Task:', task) #Task: <Task pending name='Task-1' coro=<request() running at /Users/demo.py>> task.add_done_callback(callback) #给task任务绑定回调函数 print('Task:', task) #Task: <Task pending name='Task-1' coro=<request() running at /Users/demo.py:25> cb=[callback() at /Users/demo.py]>loop = asyncio.get_event_loop() #创建一个事件循环 print('Task:', task)#进入事件循环 Task: <Task pending name='Task-1' coro=<request() running at /Users/demo.py>>loop.run_until_complete(task) #将协程当做任务提交到事件循环的任务列表中,协程执行完成之后终止 print('Task:', task)#关闭事件循环 '''*** Status: 123 Task: <Task finished name='Task-1' coro=<request() done, defined at /Users/demo.py> result=123> '''print('Task Result:', task.result()) # Task Result: 123

通过task.add_done_callback(callback)方法给task任务添加回调函数,当task(也可以说是coroutine)执行完成的时候,就会调用回调函数。并通过future,result()获取协程执行的结果。
这里我们创建 的task和回调里的future对象实际上是同一个对象。

await

await是一个只能在协程函数中使用的关键字,用于遇到耗时(IO)的操作时事件循环将会挂起 当前协程(任务),去执行其他的协程(任务),直到其他的协程也挂起或者执行完毕,再进行下一个协程的执行。当前协程IO处理完成时,可以再次切换回来执行await之后的代码。

耗时的操作一般是一些IO操作,例如网络请求,文件读取等。协程的目的也是让这些IO操作异步化。

注意: await语法只能出现在通过async修饰的函数中,否则会报SyntaxError错误

这里耗时操作可使用asyncio.sleep函数来模拟IO操作

async def request(x):print("waiting:",x)# 当前协程挂起时,事件循环可以去执行其他协程(任务)。await asyncio.sleep(x)return 123

协程来回切换执行的意义

计算型的操作,利用协程来回切换执行,没有任何意义,来回切换并保存状态 反倒会降低性能。
IO型的操作,利用协程在IO等待时间就去切换执行其他任务,当IO操作结束后再自动回调,那么就会大大节省资源并提供性能,从而实现异步编程(不等待任务结束就可以去执行其他代码)。

协程一般应用在有IO操作的程序中,因为协程可以利用IO等待的时间去执行一些其他的代码,从而提升代码执行效率

结合yield

参考:https://www.cnblogs.com/dhcn/p/9032461.html

import asyncio all_potatos = [1,2,3,4,5]#当生产者完成和返回之后,这是便能从await挂起的地方继续往下跑,完成消费的过程。而这整一个过程,就是一个异步生成器迭代的流程 async def ask_for_potato():await asyncio.sleep(random.random())all_potatos.extend(Potato.make(random.randint(1, 10)))async def take_potatos(num):count = 0while True:if len(all_potatos) == 0:#当货架上的土豆没有了之后,我可以询问超市请求需要更多的土豆,这时候需要等待一段时间直到生产者完成生产的过程await ask_for_potato()potato = all_potatos.pop()yield potatocount += 1if count == num:breakasync def buy_potatos():bucket = []#async for语法表示我们要后面迭代的是一个异步生成器。async for p in take_potatos(50):bucket.append(p)print('Got potato =',p)if __name__ == '__main__':loop = asyncio.get_event_loop()res = loop.run_until_complete(buy_potatos())loop.close()

参考博客:
https://zhuanlan.zhihu.com/p/137057192

https://www.cnblogs.com/zhaof/p/8490045.html
https://blog.csdn.net/qq_27825451/article/details/86292513
https://zhuanlan.zhihu.com/p/69210021

总结

以上是生活随笔为你收集整理的python中重要的模块asyncio的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。