协程库 gevent

gevent,它是一个并发网络库。它的协程是基于greenlet的,并基于libev实现快速事件循环(Linux上是epoll,FreeBSD上是kqueue,Mac OS X上是select),协程阻塞时会自动调度(前提是打猴子补丁)

def demo_00():
    import time
    import gevent
    #from gevent import monkey 
    #monkey.patch_all()
    '''
        也可以用gevent中提供的sleep函数替代time.sleep
        一般推荐使用猴子补丁
    '''
    def func(a,b):
        print(a,b)
        time.sleep(3) # 标准库time.sleep是阻塞式的

    f1 = gevent.spawn(func, 1,2)
    f2 = gevent.spawn(func,3,4)

    print(f1.started)
    print(f2.started)
    f1.join() # 此时是f1执行完毕才执行f2  >> 1 2 休眠 3 4 休眠
    f2.join() # 去掉注释 f1休眠期间会打印 3,4 
协程的执行方法.join/.start

join是阻塞式执行。 start是非阻塞式的即父协程结束,程序结束

def demo_01():
    import gevent
    def func():
        print('协程休眠')
        gevent.sleep(3) 
        print('休眠结束')

    f1 = gevent.spawn(func)   
    f1.start()
    time.sleep(1)
  • ”gevent.joinall()”方法会等待所有传入的greenlet协程运行结束后再退出, 这个方法可以接受一个”timeout”参数来设置超时时间,单位是秒。等待时间超过还未结束便不会继续等待。

  • greenlet一个协程运行完后,必须显式切换,不然会返回其父协程。而在gevent中,一个协程运行完后,它会自动调度那些未完成的协程。

def demo_02():
    import gevent
    def test1():
        print(12)
        gevent.sleep(0)
        print(34)

    def test2():
        print(56)
        gevent.sleep(0)
        print(78)
    jobs = [gevent.spawn(test1),gevent.spawn(test2)]
    gevent.joinall(jobs,timeout=5)
    print([job.exception for job in jobs])
协程函数的执行状态,返回值与异常

协程状态有已启动和已停止,分别可以用协程对象的”started”属性和”ready()”方法来判断。对于已停止的协程,可以用”successful()”方法来判断其是否成功运行且没抛异常。如果协程执行完有返回值,可以通过”value”属性来获取。另外,greenlet协程运行过程中发生的异常是不会被抛出到协程外的,因此需要用协程对象的”exception”属性来获取协程中的异常。

def demo_03():
    import gevent

    def win():
        return 'You win!'

    def fail():
        raise Exception('You failed!')

    winner = gevent.spawn(win)
    loser = gevent.spawn(fail)

    print(winner.started)  # True
    print(loser.started ) # True

    # 在Greenlet中发生的异常,不会被抛到Greenlet外面。
    # 控制台会打出Stacktrace,但程序不会停止
    try:
        gevent.joinall([winner, loser])
    except Exception as e:
        # 这段永远不会被执行
        print('This will never be reached')

    print(winner.ready() ) # True
    print(loser.ready() ) # True

    print(winner.value)  # 'You win!'
    print(loser.value) # None

    print(winner.successful() ) # True
    print(loser.successful() ) # False

    # 这里可以通过raise loser.exception 或 loser.get()
    # 来将协程中的异常抛出
    print(loser.exception)

参考:

百度
廖雪峰 gevent
Python之路-python(Queue队列、进程、Gevent协程、Select\Poll\Epoll异步IO与事件驱动)
gevent:轻松异步 I/O
基于协程的Python网络库gevent介绍

你可能感兴趣的:(协程库 gevent)