Python协程之Gevent

发布时间:2019-09-05 07:03:52编辑:auto阅读(1562)

    协程,又称微线程,即为轻量级的线程。
    python中实现协程是基于Gevent模块,Gevent模块内部封装了greenlet模块;greenlet模块实现了在单线程中切换状态,Gevent模块在此之上还实现了遇到I/O操作自动切换,使程序运行更快;但是Gevent只在遇到自己认识的I/O操作时切换,所以需要使用Gevent包的一个模块:猴子补丁,使用了这个补丁,Gevent会直接修改在它之后导入的模块中的I/O操作,使其可以让Gevent识别,从而开启协程。
    Greenlet与Gevent模块都是python的第三方模块,需安装使用。

    1、Greenlet

    主要方法:

    g = greenlet(run=None, parent=None):实例化一个greenlet对象
    g.parent:每一个协程都有一个父协程,当前协程结束后会回到父协程中执行,该属性默认是创建该协程的协程
    g.run: 该属性是协程实际运行的代码. run方法结束了,那么该协程也就结束了
    g.switch(*args, **kwargs): 切换到g协程
    g.throw(): 切换到g协程,接着抛出一个异常

    示例:

    from greenlet import greenlet
    
    def work():
        print("1")
        g2.switch() # 切换到g2协程
        print("3")
        g2.switch()
    
    def work2():
        print("2")
        g1.switch()
        print("4")
    
    g1 = greenlet(work)  # 创建一个greenlet实例
    g2 = greenlet(work2)
    g1.switch() # 切换到g1协程

    结果:

    1
    2
    3
    4

    2、Gevent

    示例1:

    from gevent import monkey
    monkey.patch_all()      # monkey补丁会将在它之后导入的模块的IO操作打包,使gevent认识他们
    import gevent
    
    def work1():
        print("1")
        gevent.sleep(1)
        print("3")
    
    def work2():
        print("2")
        gevent.sleep(1)
        print("4")
    
    g1 = gevent.spawn(work1)
    g2 = gevent.spawn(work2)
    
    # g1.join()
    # g2.join()
    
    gevent.joinall([g1,g2])

    示例2:爬取网页

    from gevent import monkey;monkey.patch_all()
    import gevent
    import requests
    
    def get_url(url):
        res = requests.get(url)
        print(url,res.status_code,len(res.text))
    
    url_l = [
        'http://www.baidu.com',
        'http://www.google.com',
        'https://zh.wikipedia.org/wiki/Wikipedia:%E9%A6%96%E9%A1%B5',
        'https://www.youtube.com/?app=desktop',
        'https://www.facebook.com/',
        'http://www.python.org',
        'http://www.cnblogs.com'
    ]
    g_l = []
    for i in url_l:
        g_l.append(gevent.spawn(get_url,i))
    gevent.joinall(g_l)

关键字