1、协程
- 协程,又称微线程,英文名Coroutine。
1.1 协程是啥
- 协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元,为啥说它是一个执行单元,因为它自带CPU上下文,这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程,只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的
- 通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定
yield
import time
def task1():
while True:
print("---1----")
time.sleep(0.1)
yield
def task2():
while True:
print("---2----")
time.sleep(0.1)
yield
def main():
t1 = task1()
t2 = task2()
# 先让t1运行一会,当t1中遇到yield的时候,再返回到26行,
# 然后执行t2,当它遇到yield的时候,再次切换到t1中
# 这样t1/t2/t1/t2的交替运行,最终实现了多任务....协程
while True:
next(t1)
next(t2)
if __name__ == "__main__":
main()
greenlet
from greenlet import greenlet
import time
def test1():
while True:
print("---A--")
# 切换到test2()中执行
gr2.switch()
time.sleep(0.5)
def test2():
while True:
print("---B--")
# 切换到test1()中执行
gr1.switch()
time.sleep(0.5)
gr1 = greenlet(test1)
gr2 = greenlet(test2)
# 切换到gr1中运行
gr1.switch()
gevent
- greenlet已经实现了协程,但是这个还的人工切换,太麻烦了,python还有一个比greenlet更强大的并且能够自动切换任务的模块gevent
- 其原理是当一个greenlet遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行
- 由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO
import gevent
# import time
def f1(n):
for i in range(n):
# gevent.getcurrent() 获取当前变量的内存地址
print(gevent.getcurrent(), i)
# time.sleep(0.5)
# 遇到延时就切换
gevent.sleep(0.5)
def f2(n):
for i in range(n):
print(gevent.getcurrent(), i)
# time.sleep(0.5)
gevent.sleep(0.5)
def f3(n):
for i in range(n):
print(gevent.getcurrent(), i)
# time.sleep(0.5)
gevent.sleep(0.5)
print("----1---")
g1 = gevent.spawn(f1, 5)
print("----2---")
g2 = gevent.spawn(f2, 5)
print("----3---")
g3 = gevent.spawn(f3, 5)
print("----4---")
# 等待执行结束
g1.join()
g2.join()
g3.join()
打补丁
import gevent
import time
from gevent import monkey
monkey.patch_all()
def f1(n):
for i in range(n):
print(gevent.getcurrent(), i)
time.sleep(0.5)
def f2(n):
for i in range(n):
print(gevent.getcurrent(), i)
time.sleep(0.5)
def f3(n):
for i in range(n):
print(gevent.getcurrent(), i)
time.sleep(0.5)
print("----1---")
g1 = gevent.spawn(f1, 5)
print("----2---")
g2 = gevent.spawn(f2, 5)
print("----3---")
g3 = gevent.spawn(f3, 5)
print("----4---")
g1.join()
g2.join()
g3.join()