协程

  1. 协程
    协程是一种比线程更加轻量级的存在,正如一个进程可以拥有多个线程一样,一个线程可以拥有多个协程。协程不是被操作系统内核管理,而是完全由程序所控制。线程和进程的操作是由程序触发系统接口,最后的执行者是系统,协程的操作是程序员。
  2. python3协程池 python协程的原理_简单实现

  3. 意义:对于多线程的应用,CPU通过切片的方式来切换协程之间的执行,线程之间的切换需要耗时(保存状态,下次继续)。协程则只使用一个线程(单线程),在一个线程中规定某个代码快执行顺序。
  4. python3协程池 python协程的原理_单线程_02

  5. 协程的应用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程
    理解:在一个线程中的某个函数,可以在任何地方保存函数的一些临时变量,然后切换到另外一个函数,注意不是通过调用函数的方式做到,并且切换的次数以及何时切换都是由程序员掌控。协程就是可以暂停执行的函数。
  6. 协程的简单实现
"""
1.创建work1的生成器
2.获取work2的生成器
3.获取生成器,通过next运行生成器
"""
# 1.创建work1的生成器
import time


def work1():
    while True:
        print('正在执行work1...')
        yield
        time.sleep(1)


def work2():
    while True:
        print('正在执行work2...')
        yield
        time.sleep(1)


if __name__ == '__main__':
    w1 = work1()
    w2 = work2()
    while True:
        next(w1)
        next(w2)

上面的程序就实现了一个简答的协程。实现单线程两个任务同时切换。

4. greenlet
Greenlet是python的一个C扩展,可以提供可自行调度的微线程,也就是协程。

"""
1.创建work1的生成器
2.获取work2的生成器
3.获取生成器,通过next运行生成器
"""

"""
greenlet实现协程的步骤
1.导入模块
2.创建任务work1,work2
3.创建greenlet对象
4.手动切换任务
"""
# 1.创建work1的生成器
import time
from greenlet import greenlet


def work1():
    while True:
        print('正在执行work1...')
        yield
        time.sleep(1)
        # 切换到第二个任务
        g2.switch()


def work2():
    while True:
        print('正在执行work2...')
        yield
        time.sleep(1)
        # 切换到第一个任务
        g1.switch()


if __name__ == '__main__':

    # 创建greenlet对象
    g1 = greenlet(work1)
    g2 = greenlet(work2)

    # 执行work1
    g1.switch()

5. grvent
由于IO操作非常耗时,经常使程序处于等待状态,有了grevent为我们自动切换协程,就保证greenlet在运行,而不是等待IO。

"""
# 自动识别程序中耗时操作,在耗时的时候自动切换到其他任务
1.导入模块
2.指派任务

"""
# 1.创建work1的生成器
import time
import gevent


def work1():
    while True:
        print('正在执行work1...')
        gevent.sleep(1)


def work2():
    while True:
        print('正在执行work2...')
        # gevent识别不了,time.sleep()是延时操作
        # time.sleep(1)
        gevent.sleep(1)


if __name__ == '__main__':
    # 指派任务
    # gevent.spawn(函数名,参数1,参数2,参数3,....)
    g1 = gevent.spawn(work1)
    g2 = gevent.spawn(work2)

    # 让主线程等待协程执行完毕再退出
    g1.join()
    g2.join()

上面的程序中gevent识别不了time.sleep()是延迟操作,因此有可以使用打补丁的方法:


1. 导入模块
 from gevent import monkey2. 破解monkey.patch_all()
 monkey.patch_all()

上面两步完成之后,就可以识别了。