天天看点

Python协程

协程是 <code>python</code> 中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。为啥说它是一个执行单元,因为它自带 <code>cpu</code> 上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。只要这个过程中保存或恢复 <code>cpu</code> 上下文那么程序还是可以运行的。

通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定

在实现多任务时,线程切换从系统层面远不止保存和恢复 cpu上下文这么简单。操作系统为了程序运行的高效性每个线程都有自己缓存 <code>cache</code> 等数据,操作系统还会帮你做这些数据的恢复操作。所以线程的切换非常耗性能。但是 协程的切换只是单纯的操作 <code>cpu</code> 的上下文,所以一秒钟切换个上百万次系统都抗的住。

运行结果:

为了更好使用协程来完成多任务,<code>python</code> 中的 <code>greenlet</code> 模块对其封装,从而使得切换任务变的更加简单

使用如下命令安装 <code>greenlet</code> 模块:

代码演示

运行效果:

<code>greenlet</code> 已经实现了协程,但是这个还的人工切换,是不是觉得太麻烦了,不要着急,python还有一个比greenlet更强大的并且能够 自动切换任务 的模块 <code>gevent</code>

其原理是当一个 <code>greenlet</code> 遇到 <code>io操作</code>(指的是input output 输入输出,比如网络、文件操作等)时,比如访问网络,就自动切换到其他的 <code>greenlet</code>,等到 <code>io操作</code> 完成,再在适当的时候切换回来继续执行。

由于 <code>io操作</code> 非常耗时,经常使程序处于等待状态,有了 <code>gevent</code> 为我们自动切换协程,就保证总有 <code>greenlet</code>在运行,而不是等待 <code>io</code>

首先安装模块

可以看到,3个 <code>greenlet</code>  是依次运行而不是交替运行

将程序中用到的耗时操作的代码, 换为 <code>gevent</code> 中自己实现的模块才会自行切换,看看打补丁后。

https://mp.weixin.qq.com/s/6suxfxo00ajomh3bz5jfvw