Python异步编程是什么,有何用处
Admin 2022-05-24 群英技术资讯 443 次浏览
异步编程是一种并发编程的模式,其关注点是通过调度不同任务之间的执行和等待时间,通过减少处理器的闲置时间来达到减少整个程序的执行时间;异步编程跟同步编程模型最大的不同就是其任务的切换,当遇到一个需要等待长时间执行的任务的时候,我们可以切换到其他的任务执行;
与多线程和多进程编程模型相比,异步编程只是在同一个线程之内的的任务调度,无法充分利用多核CPU的优势,所以特别适合IO阻塞性任务;
python 版本 3.9.5
python提供了asyncio模块来支持异步编程,其中涉及到coroutines
、event loops
、futures
三个重要概念;
event loops主要负责跟踪和调度所有异步任务,编排具体的某个时间点执行的任务;
coroutines是对具体执行任务的封装,是一个可以在执行中暂停并切换到event loops执行流程的特殊类型的函数;其一般还需要创建task才能被event loops调度;
futures负责承载coroutines的执行结果,其随着任务在event loops中的初始化而创建,并随着任务的执行来记录任务的执行状态;
异步编程框架的整个执行过程涉及三者的紧密协作;
首先事件循环启动之后,会从任务队列获取第一个要执行的coroutine,并随之创建对应task和future;
然后随着task的执行,当遇到coroutine内部需要切换任务的地方,task的执行就会暂停并释放执行线程给event loop,event loop接着会获取下一个待执行的coroutine,并进行相关的初始化之后,执行这个task;
随着event loop执行完队列中的最后一个coroutine才会切换到第一个coroutine;
随着task的执行结束,event loops会将task清除出队列,对应的执行结果会同步到future中,这个过程会持续到所有的task执行结束;
每个任务执行中间会暂停给定的时间,循序执行的时间就是每个任务执行的时间加和;
import time def count_down(name, delay): indents = (ord(name) - ord('A')) * '\t' n = 3 while n: time.sleep(delay) duration = time.perf_counter() - start print('-' * 40) print(f'{duration:.4f} \t{indents}{name} = {n}') n -= 1 start = time.perf_counter() count_down('A', 1) count_down('B', 0.8) count_down('C', 0.5) print('-' * 40) print('Done') # ---------------------------------------- # 1.0010 A = 3 # ---------------------------------------- # 2.0019 A = 2 # ---------------------------------------- # 3.0030 A = 1 # ---------------------------------------- # 3.8040 B = 3 # ---------------------------------------- # 4.6050 B = 2 # ---------------------------------------- # 5.4059 B = 1 # ---------------------------------------- # 5.9065 C = 3 # ---------------------------------------- # 6.4072 C = 2 # ---------------------------------------- # 6.9078 C = 1 # ---------------------------------------- # Done
python在语法上提供了async
、await
两个关键字来简化将同步代码修改为异步;
async使用在函数的def关键字前边,标记这是一个coroutine函数;
await用在conroutine里边,用于标记需要暂停释放执行流程给event loops;
await 后边的表达式需要返回waitable的对象,例如conroutine、task、future等;
asyncio模块主要提供了操作event loop的方式;
我们可以通过async将count_down标记为coroutine,然后使用await和asyncio.sleep来实现异步的暂停,从而将控制权交给event loop;
async def count_down(name, delay, start): indents = (ord(name) - ord('A')) * '\t' n = 3 while n: await asyncio.sleep(delay) duration = time.perf_counter() - start print('-' * 40) print(f'{duration:.4f} \t{indents}{name} = {n}') n -= 1
我们定义一个异步的main方法,主要完成task的创建和等待任务执行结束;
async def main(): start = time.perf_counter() tasks = [asyncio.create_task(count_down(name,delay,start)) for name, delay in [('A', 1),('B', 0.8),('C', 0.5)]] await asyncio.wait(tasks) print('-' * 40) print('Done')
执行我们可以看到时间已经变为了执行时间最长的任务的时间了;
asyncio.run(main()) # ---------------------------------------- # 0.5010 C = 3 # ---------------------------------------- # 0.8016 B = 3 # ---------------------------------------- # 1.0011 A = 3 # ---------------------------------------- # 1.0013 C = 2 # ---------------------------------------- # 1.5021 C = 1 # ---------------------------------------- # 1.6026 B = 2 # ---------------------------------------- # 2.0025 A = 2 # ---------------------------------------- # 2.4042 B = 1 # ---------------------------------------- # 3.0038 A = 1 # ---------------------------------------- # Done
异步编程要求具体的任务必须是coroutine,也就是要求方法是异步的,否则只有任务执行完了,才能将控制权释放给event loop;
python中的concurent.futures提供了ThreadPoolExecutor和ProcessPoolExecutor,可以直接在异步编程中使用,从而可以在单独的线程或者进程至今任务;
import time import asyncio from concurrent.futures import ThreadPoolExecutor def count_down(name, delay, start): indents = (ord(name) - ord('A')) * '\t' n = 3 while n: time.sleep(delay) duration = time.perf_counter() - start print('-'*40) print(f'{duration:.4f} \t{indents}{name} = {n}') n -=1 async def main(): start = time.perf_counter() loop = asyncio.get_running_loop() executor = ThreadPoolExecutor(max_workers=3) fs = [ loop.run_in_executor(executor, count_down, *args) for args in [('A', 1, start), ('B', 0.8, start), ('C', 0.5, start)] ] await asyncio.wait(fs) print('-'*40) print('Done.') asyncio.run(main()) # ---------------------------------------- # 0.5087 C = 3 # ---------------------------------------- # 0.8196 B = 3 # ---------------------------------------- # 1.0073 A = 3 # ---------------------------------------- # 1.0234 C = 2 # ---------------------------------------- # 1.5350 C = 1 # ---------------------------------------- # 1.6303 B = 2 # ---------------------------------------- # 2.0193 A = 2 # ---------------------------------------- # 2.4406 B = 1 # ---------------------------------------- # 3.0210 A = 1 # ---------------------------------------- # Done.
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
Python之中最好的图表库叫matplotlib,matplotlib,顾名思义就是提供了一整套和matlab相似的API,它的文档相当完备,下面这篇文章主要给大家介绍了关于python如何利用matplotlib绘制并列双柱状图并标注数值的相关资料,需要的朋友可以参考下
这篇文章主要为大家介绍了Python基于ssh远程连接Mysql数据库操作示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
这篇文章主要给大家分享python中的四个高级数据类型,分别是字符,元组,列表,字典,下文实例介绍的很详细,对大家学习和理解python数据类型有一定的帮助,有需要的朋友可以参考,接下来跟随小编一起学习一下吧。
大部分程序和语言中的随机数,其实都只是伪随机。是由可确定的函数(常用线性同余),通过一个种子(常用时钟)产生的。直观来想,计算机就是一种确定的、可预测的的设备:一行行的代码是固定的,一步步的算法是固定的,一个个与非门是固定的。
时间戳又被称之为是Unix时间戳,原本是在Unix系统中的计时工具。它的含义是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。UNIX时间戳的 0 按照ISO 8601规范为 :1970-01-01T00:00:00Z。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008