• Python协程gevent


    gevent

    greenlet已经实现了协程,但是这个需要人工切换,是不是觉得太麻烦了,不要捉急,python还有一个比greenlet更强大的并且能够自动切换任务的模块gevent
    其原理是当一个greenlet遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。
    由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO

    优势

    代码中调用方便;

    • 拥有的monkey机制;
    • monkey机制

    假设你不愿意修改原来已经写好的python代码,但是又想充分利用gevent机制,那么你就可以用monkey来做到这一点。你所要做的就是在文件开头打一个patch,那么它就会自动替换你原来的thread、socket、time、multiprocessing等代码,全部变成gevent框架。这一切都是由gevent自动完成的。注意这个patch是在所有module都import了之后再打,否则没有效果。

    安装

    pip3 install gevent
    

    使用

    import gevent
    
    def f(n):
        for i in range(n):
            print(gevent.getcurrent(), i)
    
    g1 = gevent.spawn(f, 5)
    g2 = gevent.spawn(f, 5)
    g3 = gevent.spawn(f, 5)
    g1.join()
    g2.join()
    g3.join()
    

    运行结果

    <Greenlet at 0x10e49f550: f(5)> 0
    <Greenlet at 0x10e49f550: f(5)> 1
    <Greenlet at 0x10e49f550: f(5)> 2
    <Greenlet at 0x10e49f550: f(5)> 3
    <Greenlet at 0x10e49f550: f(5)> 4
    <Greenlet at 0x10e49f910: f(5)> 0
    <Greenlet at 0x10e49f910: f(5)> 1
    <Greenlet at 0x10e49f910: f(5)> 2
    <Greenlet at 0x10e49f910: f(5)> 3
    <Greenlet at 0x10e49f910: f(5)> 4
    <Greenlet at 0x10e49f4b0: f(5)> 0
    <Greenlet at 0x10e49f4b0: f(5)> 1
    <Greenlet at 0x10e49f4b0: f(5)> 2
    <Greenlet at 0x10e49f4b0: f(5)> 3
    <Greenlet at 0x10e49f4b0: f(5)> 4
    

    可以看到,3个greenlet是依次运行而不是交替运行,这是因为没有遇到阻塞(io阻塞或其他阻塞),让程序不能退出,那么程序遇到阻塞就会切换到func协程函数里面执行

    gevent切换执行

    import gevent
    
    def f(n):
        for i in range(n):
            print(gevent.getcurrent(), i)
            #用来模拟一个耗时操作,注意不是time模块中的sleep
            gevent.sleep(1)
    
    g1 = gevent.spawn(f, 5)   # 将事件函数加入协程,就变成协程函数了
    g2 = gevent.spawn(f, 5)
    g3 = gevent.spawn(f, 5)
    # g1.join()
    # g2.join()
    # g3.join()
    gevent.joinall([g1, g2,g3])   # 回收协程,比一个一个回收方便一点
    

    运行结果

    <Greenlet at 0x7fa70ffa1c30: f(5)> 0
    <Greenlet at 0x7fa70ffa1870: f(5)> 0
    <Greenlet at 0x7fa70ffa1eb0: f(5)> 0
    <Greenlet at 0x7fa70ffa1c30: f(5)> 1
    <Greenlet at 0x7fa70ffa1870: f(5)> 1
    <Greenlet at 0x7fa70ffa1eb0: f(5)> 1
    <Greenlet at 0x7fa70ffa1c30: f(5)> 2
    <Greenlet at 0x7fa70ffa1870: f(5)> 2
    <Greenlet at 0x7fa70ffa1eb0: f(5)> 2
    <Greenlet at 0x7fa70ffa1c30: f(5)> 3
    <Greenlet at 0x7fa70ffa1870: f(5)> 3
    <Greenlet at 0x7fa70ffa1eb0: f(5)> 3
    <Greenlet at 0x7fa70ffa1c30: f(5)> 4
    <Greenlet at 0x7fa70ffa1870: f(5)> 4
    <Greenlet at 0x7fa70ffa1eb0: f(5)> 4
    

    给程序打补丁

    from gevent import monkey
    import gevent
    import random
    import time
    
    # 有耗时操作时需要
    monkey.patch_all()  # 将程序中用到的耗时操作的代码,换为gevent中自己实现的模块,这两行是为了改变模块一些特性,如time模块,socket模块,这样才能识别time.sleep()与sock.accept()与sock.recv()等为阻塞函数,进行切换。
    
    def coroutine_work(coroutine_name):
        for i in range(10):
            print(coroutine_name, i)
            time.sleep(random.random())
    
    gevent.joinall([
            gevent.spawn(coroutine_work, "work1"),
            gevent.spawn(coroutine_work, "work2")
    ])
    

    运行结果

    work1 0
    work2 0
    work1 1
    work1 2
    work1 3
    work2 1
    work1 4
    work2 2
    work1 5
    work2 3
    work1 6
    work1 7
    work1 8
    work2 4
    work2 5
    work1 9
    work2 6
    work2 7
    work2 8
    work2 9
    
  • 相关阅读:
    4.2网络层提供的两种服务
    4.1网络层概述
    MATLAB曲面插值及交叉验证
    python爬虫成长之路(二):抓取代理IP并多线程验证
    KNN识别图像上的数字及python实现
    python爬虫成长之路(一):抓取证券之星的股票数据
    YARN环境搭建 之 一:CentOS7.0系统配置
    高效学习方法总结
    《立委随笔:机器学习和自然语言处理》
    XenServer安装虚拟机先扩容存放ISO镜像文件
  • 原文地址:https://www.cnblogs.com/feng0815/p/16554383.html
Copyright © 2020-2023  润新知