一、协程
协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)
通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定
二、协程的实现
方式一:yield
# 实现协程
import time
def test1():
while True:
print('test1')
yield
time.sleep(0.2)
def test2():
while True:
print('test2')
yield
time.sleep(0.2)
def main():
t1 = test1()
t2 = test2()
while True:
next(t1)
next(t2)
if __name__ == '__main__':
main()
运行结果:
方式二:使用greenlet实现协程
安装greenlet:命令如下
windows:pip install greenlet
Linux:sudo pip install greenlet
from greenlet import greenlet
import time
def test1():
while True:
print "---A--"
# 切换到gr2中
gr2.switch()
time.sleep(0.5)
def test2():
while True:
print "---B--"
# 切换到gr1中运行
gr1.switch()
time.sleep(0.5)
gr1 = greenlet(test1)
gr2 = greenlet(test2)
# 切换到gr1中运行
gr1.switch()
运行结果:
—A–
—B–
—A–
—B–
…省略…
方式三:使用gevent实现协程
安装gevent:命令如下
windows:pip install gevent
Linux:sudo pip install gevent
import gevent
def f(n):
for i in range(n):
print(gevent.getcurrent(), i)
#用来模拟一个耗时操作,注意不是time模块中的sleep
gevent.sleep(1)
# g1 = gevent.spawn(f, 5)
# g2 = gevent.spawn(f, 5)
# g3 = gevent.spawn(f, 5)
# g1.join()
# g2.join()
# g3.join()
# 上面的创建协程,等待完成可用下面这种方法代替
gevent.joinall([
gevent.spawn(f, 5),
gevent.spawn(f, 5),
gevent.spawn(f, 5)
])
运行结果:
gevent实现协程时,当遇见gevent.sleep()时及gevent耗时,就会执行另一个协程,可能你已经使用了time模块的sleep()方法实现耗时,这样还是无法实现,我们必须将耗时改成gevent中的耗时,可能你的代码中出现了很多的time.sleep() 修改起来很麻烦,我们只需要给程序打个补丁即可。
导入模块
from gevent import monkey
打补丁
monkey.patch_all()
三、进程、线程、协程的区别
- 进程是资源分配的单位
- 线程是操作系统调度的单位
- 进程切换需要的资源很最大,效率很低
- 线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下)
- 协程切换任务资源很小,效率高
- 多进程、多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中 所以是并发