• (20)gevent协程


    协程: 也叫纤程,协程是线程的一种实现,指的是一条线程能够在多任务之间来回切换的一

    种实现,对于CPU、操作系统来说,协程并不存在

    任务之间的切换会花费时间.目前电脑配置一般线程开到200会阻塞卡顿 .

    协程的实现: 协程帮助你记住哪个任务执行到哪个位置上了,并且实现安全的切换

    一个任务一旦阻塞卡顿,立刻切换到另一个任务继续执行,保证线程总是忙碌的,更加充

    分的利用,

    CPU,抢占更多的时间片

    一个线程可以由多个协程来实现,协程之间不会产生数据安全问题

    协程模块:

    greenlet gevent的底层,协程,切换的模块

    gevent 直接用的,gevent能提供更全面的功能

    (1) 用生成器写生产者消费者模型

    # producer 生产者
    def producer():
        for i in range(10):
            yield i
    # consumer 消费者
    def consumer():
        g = producer()
        for num in g:
            print(num)
    consumer()
    View Code

    执行结果:

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    View Code

    (2) 普通版 greenlet+switch组合 基本实现,只能用switch进行手动切换,

    缺陷:不能规避雕io,不能自动实现遇到阻塞就切换.

    from greenlet import greenlet
    import time
    def eat():
        print("eat one1")
        # 切换到play这个协程中
        g2.switch()
        time.sleep(1)
        print("eat one2")
    def play():
        print("play one1")
        print("play one2")
        g1.switch()
    g1 = greenlet(eat)
    g2 = greenlet(play)
    g1.switch()
    View Code

    执行结果

    eat one1
    play one1
    play one2
    eat one2
    View Code

    (3) 升级版 gevent+spawn组合 有缺陷,不能够识别time.sleep()

    spawn 自动检测阻塞,遇到阻塞就切换,相当于switch 的升级版 

    import gevent,time
    def eat():
        print("eat one1")
        time.sleep(1)
        print("eat one2")
    def play():
        print("play one1")
        time.sleep(1)
        print("play one2")
    g1 = gevent.spawn(eat)
    g2 = gevent.spawn(play)
    # 协程的阻塞也是join
    g1.join()  # 阻塞直到g1协程执行完毕
    g2.join()  # 阻塞直到g2协程执行完毕
    View Code

    执行结果:发现者并不是我们我们希望的结果

    eat one1
    eat one2
    play one1
    play one2
    View Code

    (4) 进阶版本 用gevent.sleep() 取代time.sleep()

    import gevent
    def eat():
        print("eat one1")
        gevent.sleep(1)
        print("eat one2")
    def play():
        print("play one1")
        gevent.sleep(1)
        print("play one2")
    g1 = gevent.spawn(eat)
    g2 = gevent.spawn(play)
    # 协程的阻塞也是join
    g1.join()  # 阻塞直到g1协程执行完毕
    g2.join()  # 阻塞直到g2协程执行完毕
    View Code

    执行结果:问题是解决了,但是看起来怪怪的,改变了原有的time,sleep()语法

    eat one1
    play one1
    eat one2
    play one2
    View Code

    (5) 终极解决办法 gevent+spawn +monkey.patch_all()

    from gevent import monkey;monkey.patch_all()
    import time,gevent
    def eat():
        print("eat one1")
        time.sleep(1)
        print("eat one2")
    def play():
        print("play one1")
        time.sleep(1)
        print("play one2")
    g1 = gevent.spawn(eat)
    g2 = gevent.spawn(play)
    # 协程的阻塞也是join
    g1.join()  # 阻塞直到g1协程执行完毕
    g2.join()  # 阻塞直到g2协程执行完毕
    View Code

    执行结果:perfect 完美!你没有看错,就是这只猴子,老厉害了,解决了所有问题

    eat one1
    play one1
    eat one2
    play one2
    View Code

    .

     

     

  • 相关阅读:
    python初学者学习工具安装教程&安装步骤详解
    Django面试题
    数据库-面试题
    Python面试题
    Python 内置函数&filter()&map()&reduce()&sorted()
    Python匿名函数(lambda函数)
    Python中两大神器&exec() &eval()
    面向对象&从这里开始我们将不再是纯小白
    软件开发程序猿日常必备,现用现查&日志记录
    如何去写项目的readme&链接
  • 原文地址:https://www.cnblogs.com/lyj910313/p/10787411.html
Copyright © 2020-2023  润新知