python协程
简介:
协程,又称微线程,纤程。英文名Coroutine。
协程是啥
协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。
为啥说它是一个执行单元,因为它自带CPU上下文。
这样只要在合适的时机,我们可以把一个协程切换到另一个协程。只要这个过程中保存或恢复CPU上下文那么程序还是可以运行的。
通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,
并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定
协程和线程差异
在实现多任务时,线程切换从系统层面远不止保存和恢复CPU上下文这么简单。操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,
操作系统还会帮你做这些数据的恢复操作。所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。
生成器创建的方式2:在def里面如果看到yield关键就是生成器
定义生成器完成fibonacci
Def fibonacci(num):
#记录数列的前两个值
a=0
b=1
current_index=0
print("--1111---")
While current_index<num:
#生成下一个数列的值
result=a
a,b=b,a+b
current_index+=1
print("--222---")
#启动生成器的时候遇到yield代码会暂停,下次启动生成器会在暂停的位置继续往下执行
params=yieldresult
print(params)
print("--3333---")
#return"哈哈"
#创建生成器
f=fibonacci(5)
#value=next(f)
#print(value)
##send方法可以给生成器传参数
#value=f.send("嘻嘻")
#print(value)
#提示:send方法第一次启动生成器的时候传入的参数必须是None,否则崩溃,一般第一次启动生成器使用next函数
value=f.send(None)
print(value)
value=f.send("嘻嘻")
print(value)
----------------------------------------------------------
协程:微纤程,也称为用户级线程,在不开辟线程的基础上完成多个任务按照一定顺序交替执行
如何理解协程:在def里面只看到一个yield关键字就是协程
学习协程的目的:
完成在单个线程的基础上多个任务交替执行,也就是完成多任务
Import time
#定义协程1
Def work1():
While True:
print("work1...")
time.sleep(0.1)
yield
#定义协程2
Def work2():
While True:
print("work2...")
time.sleep(0.1)
yield
#创建协程
g1=work1()
g2=work2()
While True:
next(g1)
next(g2)
----------------------------------------------------------
Import time
Def work1():
While True:
print("work1...")
time.sleep(0.1)
yield
Def work2():
While True:
print("work2...")
time.sleep(0.1)
yield
if__name__=='__main__':
#work1()
#work2()
g1=work1()
g2=work2()
#print(g1,g2)
While True:
next(g1)
next(g2)
Linux:pip3list:查看电脑第三方的安装包或者模块
Import greenlet
Import time
----------------------------------------------------------
#greenlet封装的是yield,为了让程序员更好的使用协程
#任务1
Def work1():
For i inrange(5):
print("work1....")
time.sleep(0.1)
#切换到协程2执行对应的任务
g2.switch()
#任务2
Def work2():
For I inrange(5):
print("work2....")
time.sleep(0.1)
#切换到协程1执行对应的任务
g1.switch()
#创建协程指定对应的任务
g1=greenlet.greenlet(work1)
g2=greenlet.greenlet(work2)
#切换到指定协程执行对应的任务
g1.switch()
----------------------------------------------------------
Import greenlet
Import time
Def work1():
For i inrange(5):
print("work1....")
time.sleep(0.1)
#切换到协成2执行对应的任务
g2.switch()
Def work2():
For i inrange(5):
print("work2....")
time.sleep(0.1)
g1.switch()
if__name__=='__main__':
#创建协成
g1=greenlet.greenlet(work1)
g2=greenlet.greenlet(work2)
g1.switch()
----------------------------------------------------------
Import gevent
Impor ttime
From gevent import monkey
#打补丁,让gevent能够识别系统的耗时操作和网络请求延时操作
#提示:这句代码一定要先执行。
monkey.patch_all()
#总结:gevent封装的是greentlet,gevent可以完成协程之间自动切换
#任务1
Def work1():
#获取当前任务执行的协程对象
Print("work1:",gevent.getcurrent())
For I inrange(10):
print("work1")
time.sleep(0.1)
#gevent.sleep(0.1)
#任务2
Def work2():
#获取当前任务执行的协程对象
print("work2:",gevent.getcurrent())
For i inrange(10):
print("work2")
time.sleep(0.1)
#gevent.sleep(0.1)
#创建协程指定对应的任务
g1=gevent.spawn(work1)
g2=gevent.spawn(work2)
#让主线程等待协程执行完成以后程序再退出
#g1.join()
#g2.join()
#方式2
gevent.joinall([g1,g2])
----------------------------------------------------------
Import gevent
Import time
From gevent import monkey
#打补丁
#monkey.patch_all()
defwork1():
foriinrange(5):
print("work1...")
#time.sleep(0.1)
gevent.sleep(0.1)
Def work2():
For iinrange(5):
print("work2...")
#time.sleep(0.1)
gevent.sleep(0.1)
if__name__=='__main__':
#创建协成
g1=gevent.spawn(work1)
g2=gevent.spawn(work2)
#让主线程等待协程执行完成以后程序再退出
#g1.join()
#g2.join()
gevent.joinall([g1,g2])