当前位置: 首页 > 图灵资讯 > 行业资讯> 一篇文章带你读懂Python的协程

一篇文章带你读懂Python的协程

发布时间:2025-03-04 22:16:16

协程,又称微线程,纤程。英文名Coroutine。

协程的概念很早就提出来了,但直到近年来才广泛应用于某些语言(如Lua)。

子程序,或函数,在所有语言中都是层次调用,如A调用B,B在执行过程中调用C,C执行返回,B执行返回,最后A执行。

因此,子程序调用是通过栈实现的,一个线程就是执行子程序。

子程序调用总是一个入口,一次返回,调用顺序明确。协程调用不同于子程序。

协程看起来像子程序,但在执行过程中,可以在子程序内部中断,然后转而执行其他子程序,然后在适当的时候返回执行。

请注意,中断一个子程序,执行其他子程序,而不是函数调用,有点像CPU中断。例如,子程序A、B:

defA():
print'1'
print'2'
print'3'
defB():
print'x'
print'y'
print'z'

假设由协程执行,在执行A的过程中,可以随时中断,执行B,B也可以在执行A的过程中中中断,结果可能是:

1
2
x
y
3
z

但A中没有调用B,因此协程调用比函数调用更难理解。

看起来A、B的执行有点像多线程,但协程的特点是一个线程执行。与多线程相比,协程有什么优势?

优点是协程执行效率高。由于子程序切换不是线程切换,而是由程序本身控制,因此与多线程相比,线程数量越多,协程的性能优势就越明显。

第二个优点是不需要多线程锁定机制,因为只有一个线程,并且没有同时编写变量冲突。在协同过程中,只需判断状态即可控制共享资源,因此执行效率远高于多线程。

因为协程是一个线程执行,如何使用多核CPU?最简单的方法是多过程+协程,它不仅充分利用多核,而且充分发挥协程的高效率,可以获得极高的性能。

Python对协程的支持仍然非常有限,用于generator的yield可以在一定程度上实现协程。虽然支持不完全,但它可以发挥相当大的力量。

来看例子:

传统的生产者消费者模型是一个线程来编写信息,一个线程可以通过锁定机制来控制队列和等待,但如果你不小心,你可能会被锁定。

如果使用协议,生产者在生产消息后直接跳转到消费者开始执行。消费者执行后,切换回生产者继续生产,效率很高:

importtimedefconsumer():
r=''
whileTrue:
n=yieldrifnotn:return
print('[CONSUMER]Consuming%s...'%n)
time.sleep(1)
r='200OK'defproduce(c):
c.next()
n=0
whilen<5:
n=n+1
print('[PRODUCER]Producing%s...'%n)
r=c.send(n)
print('[PRODUCER]Consumerreturn:%s'%r)
c.close()if__name__='__main__':
c=consumer()
produce(c)

执行结果:

注意到consumer函数是generator(生成器),将consumer传输到produce后:

首先调用c.next()启动生成器;

然后,一旦生产了东西,通过c,.send(n)切换到consumer执行;

consumer通过yield获取消息,然后通过yield将结果传回;

produce获得consumer处理结果,并继续生成下一条消息;

通过croduce决定不生产produce.close()关闭consumer,整个过程结束。

整个过程无锁,由一个线程执行,produce和consumer合作完成任务,因此被称为“协程”,而不是线程的抢占式多任务。

最后,Donaldd应用程序 Knuth的一句话总结了协程的特点:

“子程序是协程的特例。”

相关文章

python3兼容python2吗

python3兼容python2吗

2025-05-09
python3 whl怎么安装

python3 whl怎么安装

2025-05-09
python 字典怎么提取value

python 字典怎么提取value

2025-05-09
python 怎样计算字符串的长度

python 怎样计算字符串的长度

2025-05-09
python 怎么样反向输出字符串

python 怎么样反向输出字符串

2025-05-09
python 怎么判断字符串开头

python 怎么判断字符串开头

2025-05-09