zoukankan      html  css  js  c++  java
  • 协程greenlet、gevent、猴子补丁

    1.协程:微线程(这个概念是在python中有的

    进程>线程>协程

    一个线程里面可以包含多个协程

    协程是通过生成器完成的,yield

    协程应用场景:

      有耗时操作的时候应用

    耗时操作:网络请求,网络下载(爬虫),IO操作(本地文件的读写),阻塞

     在函数中有yield,函数就变成了生成器,就可以使用next()方法

    import time
    
    
    # 在函数中有yield,函数就变成了生成器,就可以使用next()方法
    def task1():
        for i in range(3):
            print('A' + str(i))
            yield
            time.sleep(1)
    
    
    def task2():
        for i in range(3):
            print('B' + str(i))
            yield
            time.sleep(2)
    
    
    if __name__ == '__main__':
        g1 = task1()
        g2 = task2()
    
        while True:
            try:
                next(g1)
                next(g2)
            except:
                break
    

      

     2.使用greenlet完成协程任务

    # 使用greenlet完成协程任务
    import time
    from greenlet import greenlet
    
    
    def a():  # 任务A
        for i in range(5):
            print('A' + str(i))
            gb.switch()
            time.sleep(0.1)
    
    
    def b():  # 任务B
        for i in range(5):
            print('B' + str(i))
            gc.switch()
            time.sleep(0.1)
    
    
    def c():  # 任务C
        for i in range(5):
            print('C' + str(i))
            ga.switch()
            time.sleep(0.1)
    
    
    if __name__ == '__main__':
        ga = greenlet(a)
        gb = greenlet(b)
        gc = greenlet(c)
    
        ga.switch()
    

      

     3.gevent和猴子补丁

    greenlet已经实现了协程,但是这个人工切换,是不是觉得太麻烦了,不要着急,python还有一个比greenlet更强大的并且能够自动切换任务的模块`gevent`
    其原理是当一个greentlet遇到IO(指的是input ouput输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO完成,再适当的时候切换回来继续执行。

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

     猴子补丁,将程序中用到的耗时操作的代码,换为gevent中自己实现的模块,如time.sleep(0.1),gevent中也有sleep()方法

    import time
    import gevent
    from gevent import monkey
    
    # 有耗时操作时需要
    monkey.patch_all()  # 打补丁,将程序中用到的耗时操作的代码,换为gevent中自己实现的模块
    
    
    def a():  # 任务A
        for i in range(5):
            print('A' + str(i))
            time.sleep(0.1)
    
    
    def b():  # 任务B
        for i in range(5):
            print('B' + str(i))
            time.sleep(0.1)
    
    
    def c():  # 任务C
        for i in range(5):
            print('C' + str(i))
            time.sleep(0.1)
    
    
    if __name__ == '__main__':
        g1 = gevent.spawn(a)
        g2 = gevent.spawn(b)
        g3 = gevent.spawn(c)
    
        g1.join()
        g2.join()
        g3.join()
    

      

    4.案例

    import requests
    import gevent
    from gevent import monkey
    
    monkey.patch_all()
    
    
    def download(url):
        response = requests.get(url)  # 耗时操作
        content = response.text
        print('下载了{}的数据,长度:{}'.format(url, len(content)))
    
    
    if __name__ == '__main__':
        urls = ['http://www.163.com', 'http://www.qq.com', 'http://www.baidu.com']
        g1 = gevent.spawn(download, urls[0])
        g2 = gevent.spawn(download, urls[1])
        g3 = gevent.spawn(download, urls[2])
    
        g1.join()
        g2.join()
        g3.join()
    
        # gevent.joinall(g1, g2, g3)
    

      

  • 相关阅读:
    mysql 语句的查询过程解析
    postman 百度网盘下载 64位
    java 读取文内容(text,html)
    java把Word文件转成html的字符串返回出去
    spring boot 2.X上传文件限制大小
    nginx 做反向代理
    Linux下安装Redis
    微信小程序云开发个人博客项目实战(2)---引入-Vant-Weapp-小程序-UI-组件库
    微信小程序云开发个人博客项目实战(1)- 准备工作及引入 Vant Weapp 小程序 UI 组件库
    Video 视频播放防作弊和禁止下载
  • 原文地址:https://www.cnblogs.com/GumpYan/p/12973871.html
Copyright © 2011-2022 走看看