当前位置: 首页 > 后端技术 > Python

协程是旅行吗?

时间:2023-03-26 17:44:46 Python

Python一直在优化并发编程。多线程和多处理使用thread模块比较熟悉。后来慢慢引入了基于yield关键字的协程。在最近的版本中,python对协程的写法做了很大的优化,之前很多协程的写法官方都不推荐。协程发展历史Python中的协程大概经历了以下三个阶段:从Python3.5版本引入async/await关键字开始生成器变形yield/sendyield本文直接从Python3.5版本开始,有兴趣的可以说说在async/await关键字出现之前Python是如何完成协程的同步和异步同步的。同步是指代码调用IO操作时调用方法必须等待IO操作完成才能返回。它们之间必须有一个执行顺序。必须先执行一个,另一个才能继续执行。只有一条主线异步是指当代码调用一个IO操作时,不等待IO操作完成就直接返回。多个任务之间没有执行顺序,可以同时运行。执行顺序不会有任何影响。有多条并行并发运行的主线。我以单核CPU为例。单核意味着同一时间只能做一件事。那么在电脑上同步运行的软件是怎么做到的呢?QQ短时间在CPU执行,然后微信短时间在CPU执行。到头来,大家看起来就像是一起跑了一样。轮换策略称为时间片轮换并行:cpu大于当前执行的任务并发:cpu小于当前执行的任务协程,线程和进程的比较如果有生产线,就在这上面招更多的工人生产线一起做剪刀这样效率成倍增加,也就是单进程多线程的方法。老板发现这条生产线上的工人越多越好。因为一条生产线的资源和材料毕竟有限,所以老板花了一些钱和物力又买了一条。生产线,然后招一些工人,这样效率进一步提高,就是多进程多线程的方法3.老板发现生产线已经很多了,每条生产线上已经有很多工人了(也就是程序是多进程的,每个进程有多个线程),老板为了再次提高效率,想了个绝招,规定:如果一个员工暂时空闲在上班或者等待某些条件(比如等待另一个worker完成生产,求进程后他可以再工作),那么这个employee会利用这段时间去做其他的事情,那么也就是说:如果一个线程等待一定的条件,它可以使full利用这个时间做其他事情,其实就是:协程模式下协程的基本使用这是python3.7中协程的基本使用。现在这个用法基本稳定了,不建议再用以前的语法了。importasyncioimporttimeasyncdefvisit_url(url,response_time):"""访问url"""awaitasyncio.sleep(response_time)returnf"访问{url},返回结果已获取"start_time=time.perf_counter()task=visit_url('http://wangzhen.com',2)asyncio.run(task)print(f"消耗时间:{time.perf_counter()-start_time}")在普通函数前添加async关键字;await的意思是在这个地方等待子函数执行完成再继续。(在并发操作中,将程序控制权交给主程序,让他分配其他协程执行。)await只能在带有async关键字的函数中运行。asynco.run()运行程序。这个程序大约需要2s。添加一个协程,添加一个任务task2=visit_url('http://another.com',3)aynicio.run(task2)这两个程序总共消耗5s左右。importasyncioimporttimeasyncdefvisit_url(url,response_time):"""访问url"""awaitasyncio.sleep(response_time)returnf"访问{url},返回结果已获取"asyncdefrun_task():"""收集subtasks"""task=visit_url('http://wangzhen.com',2)task_2=visit_url('http://another',3)awaitasyncio.run(task)awaitasyncio.run(task_2)asyncio.run(run_task())print(f"消耗时间:{time.perf_counter()-start_time}")如果是并发编程,这个程序只需要消耗3s,也就是task2的等待时间。要使用并发编程形式,需要更改上面的代码。asyncio.gather将创建2个子任务,当await发生时,程序将在这2个子任务之间进行调度。asyncdefrun_task():"""收集子任务"""task=visit_url('http://wangzhen.com',2)task_2=visit_url('http://another',3)awaitasyncio.gather(task1,task2)create_task除了使用gather方法创建子任务外,还可以使用asyncio.create_task创建。asyncdefrun_task():coro=visit_url('http://wangzhen.com',2)coro_2=visit_url('http://another.com',3)task1=asyncio.create_task(coro)task2=asyncio.create_task(coro_2)awaittask1awaittask2协程的主要使用场景协程的主要使用场景是IO密集型任务。总结几个常见的使用场景:网络请求,比如爬虫,大量使用aiohttp文件读取,aiofileweb框架,aiohttp,fastapi数据库查询,asyncpg,databases