作者:手机用户2602920093 | 来源:互联网 | 2023-09-25 08:40
先来说几个概念 同步: 代码调用IO操作时,必须等到操作完成返回的调用方式,同步是并行 异步: 代码调用IO操作时,必须等到操作完成返回的调用方式,异步是串行 阻塞: 从调用者的角度说,如果调用时被卡住,不再往下执行,需要等待就是说阻塞 非阻塞: 从调用者的角度说,如果调用时没有被卡住,继续往下执行无需等待就是说非阻塞
生成器—send方法 启动生成器 发送值给生成器返回 def generator ( num) : a, b &#61; 0 , 1 con &#61; 0 while con < num: result &#61; yield a # 先执行右边&#xff0c;会阻塞在这里print ( &#39;result>>&#39; , result) a, b &#61; b, a &#43; bcon &#43;&#61; 1 return 123 g &#61; generator ( 5 ) g. close ( ) # 关闭生成器&#xff0c;后续的值将取不了 # send 方法可以启动生成器都是第一次传的值必须是空print ( next ( g) ) # 这也可以取出来print ( g. send ( &#39;huran&#39; ) ) for i in g: # 还可以用for 循环print ( i, end&#61; &#39;-&#39; ) # 捕获生成器的返回值 while True: try: ret &#61; next ( g) print ( ret) except Exception as e: print ( e. value) break
yield完成多任务 利用就是yield会阻塞的特性
import timedef task1 ( ) : while True: print ( "--1--" ) time. sleep ( 0.1 ) yielddef task2 ( ) : while True: print ( "--2--" ) time. sleep ( 0.1 ) yielddef main ( ) : t1 &#61; task1 ( ) t2 &#61; task2 ( ) while True: next ( t1) next ( t2) if __name__ &#61;&#61; "__main__" : main ( )
yield from chain&#xff08;&#xff09;可传入多个可迭代的对象&#xff0c;对他们进行一个for循环取出值来。
lis &#61; [ 1 , 2 , 3 ] dis &#61; { &#39;name&#39; : &#39;juran&#39; , &#39;age&#39; : 18 } def my_chian ( * args, * * kwargs) : for val in args: yield from valfor value in my_chian ( lis, dis) : print ( value)
yield from
def generator_1 ( ) : # 子生成器total &#61; 0 while True: x &#61; yieldprint ( &#39;加&#39; , x) if not x: break total &#43;&#61; xreturn totaldef generator_2 ( ) : # 委托生成器while True: total &#61; yield from generator_1 ( ) # 子生成器print ( &#39;加和总数是:&#39; , total) def main ( ) : # 调用方# g1 &#61; generator_1 ( ) # g1. send ( None) # g1. send ( 2 ) # g1. send ( 3 ) # g1. send ( None) g2 &#61; generator_2 ( ) g2. send ( None) g2. send ( 2 ) g2. send ( 3 ) g2. send ( None) if __name__ &#61;&#61; &#39;__main__&#39; : main ( )
【子生成器】&#xff1a;yield from后的generator_1()生成器函数是子生成器 【委托生成器】&#xff1a;generator_2()是程序中的委托生成器&#xff0c;它负责委托子生成器完成具体任务。 【调用方】&#xff1a;main()是程序中的调用方&#xff0c;负责调用委托生成器。
协程 协程&#xff0c;又称微线程 协程是python个中另外一种实现多任务的方式&#xff0c;只不过比线程更小占用更小执行单元&#xff08;理解为需要的资源&#xff09; Python中的协程大概经历了如下三个阶段&#xff1a;
最初的生成器变形yield/send yield from 在最近的Python3.5版本中引入async/await关键字 协程的实现
from greenlet import greenletimport timedef greenlet_1 ( ) : while True: print ( &#39;--1--&#39; ) g2. switch ( ) time. sleep ( 0.5 ) def greenlet_2 ( ) : while True: print ( &#39;--2--&#39; ) g1. switch ( ) time. sleep ( 0.5 ) g1 &#61; greenlet ( greenlet_1) g2 &#61; greenlet ( greenlet_2) g1. switch ( )
gevent实现多任务 遇到等待会自动切换到另外一个任务
import gevent from gevent import monkey monkey. patch_all ( ) # 将所用的噩耗时操作换为gevent模块的def test1 ( n) : for i in range ( n) : print ( gevent. getcurrent ( ) , i) gevent. sleep ( 0.5 ) # 这里会有等待&#xff0c;会自动在上一步自动切换到另外一个def test2 ( ) : while True: print ( gevent. getcurrent ( ) , &#39;---2---&#39; ) gevent. sleep ( 0.5 ) # 这里会有等待&#xff0c;会自动在上一步自动切换到另外一个t1 &#61; gevent. spawn ( test1, 2 ) # 第一个参数是对象&#xff0c;第二个是参数&#xff08;传入函数中的&#xff0c;可有可无&#xff09; t2 &#61; gevent. spawn ( test2) t1. join ( ) # 要等到执行完毕&#xff0c;否则直接到这里 t2. join ( )
案例&#xff1a;
import gevent from gevent import monkey monkey. patch_all ( ) import requestsdef download ( url) : print ( "get:%s" % url) ret &#61; requests. get ( url) data &#61; ret. textprint ( len ( data) , ret) g1 &#61; gevent. spawn ( download, &#39;https://www.kancloud.cn/ju7ran/gaoji/1474878&#39; ) g2 &#61; gevent. spawn ( download, &#39;https://fanyi.baidu.com/?fr&#61;websearch_submit&pid&#61;sogou__free#pt/zh/%3CGreenlet&#39; ) g1. join ( ) g2. join ( ) 访问的网站并不是按照你写的顺序来执行完成的&#xff0c;而是先执行完时间短一点的&#xff0c;
总结&#xff1a; 进程是资源分配的基本单位 线程是操作系统调度和执行的单位 进程切换需要的资源很最大&#xff0c;效率很低 线程切换需要的资源一般&#xff0c;效率一般&#xff08;当然了在不考虑GIL的情况下&#xff09; 协程切换任务资源很小&#xff0c;效率高 多进程、多线程根据cpu核数不一样可能是并行的&#xff0c;但是协程是在一个线程中 所以是并发