python-任务和协程文档翻译及延伸

作者: treelake | 来源:发表于2016-09-11 21:32 被阅读492次

    1. 协程概述

    • 能被asyncio调用的协程可以通过两种方式实现:

      1. 使用async def语句
      2. 使用生成器。

      第一种方式在Python3.5添加,在没有向下兼容的考虑时推荐使用。
      基于生成器的协程应该被@asyncio.coroutine
      装饰,尽管这不是严格规定(not strictly enforced)。该装饰器能够兼容async def
      定义的协程。基于生成器的协程使用 PEP 380引入的yield from语法,而不是原始的yield语法。

    • 协程一词正如生成器一词,被用于两个不同但相关的概念:

      1. 定义一个协程的函数。如果要消除歧义,我们称之为协程函数 (iscoroutinefunction()
        returns True)。
      2. 调用一个协程函数返回的对象。这个对象代表的运算和I/O操作最终将被完成。如果要消除歧义,我们称之为协程对象(iscoroutine()
        returns True)。
    • 协程能做的事情:

    1. result = await future或者result = yield from future
      暂停协程直到future被完成,然后返回future的结果,或者抛出一个异常,该异常将被传播。(如果future被取消,将抛出一个CancelledError异常。)要注意的是,tasks就是futures,一切关于futures的也适用于tasks
    2. result = await coroutine或者result = yield from coroutine
      等待另一个协程产出结果(或者抛出一个会被传播的异常)。协程表达式必须能被另一个协程调用。
    3. return expression
      产生结果给一个使用await
      或yield from来等待该协程
      的另一个协程
    4. raise exception
      抛出异常一个使用await
      或yield from来等待该协程
      的另一个协程
    • 调用一个协程并不启动它的代码运行——调用返回的协程对象什么也不做,直到你安排它执行。有两种基本的方式使它开始运行:
    1. 在另一个运行的协程中调用await coroutine或者yield from coroutine
    2. 使用ensure_future()
      函数或者AbstractEventLoop.create_task()
      方法来安排它的执行。
    • 协程(以及任务)只能在事件循环运行的时候执行。

    2. @asyncio.coroutine

    • 它是一个标记基于生成器的协程的装饰器。它使得生成器使用yield from调用async def定义的协程,并且使该生成器能够被async def定义的协程调用(比如使用await语句调用)。
    • 没有必要去装饰用async def定义的协程它们自己。
    • 如果一个生成器在销毁前没有被yield from,一个错误信息将被日志记录。参看Detect coroutines never scheduled

    3. 最简单的hello world 协程

    import asyncio
    async def hello_world(): 
        print("Hello World!")
    loop = asyncio.get_event_loop()
    # 阻塞式调用,直到hello_world()协程结束时返回
    loop.run_until_complete(hello_world())
    # run_until_complete只接受A Future, a coroutine or an awaitable
    loop.close()
    
    import asyncio
    #
    def hello_world(loop): 
        print('Hello World') 
        loop.stop()
    #
    loop = asyncio.get_event_loop()
    #
    # 安排一个hello_world()的调用
    loop.call_soon(hello_world, loop)
    #
    # 将被loop.stop()打断的阻塞式调用
    loop.run_forever()
    loop.close()
    

    4. 打印当前时间的协程

    • 在5秒时间内每秒打印当前时间,利用了sleep()
      函数
    import asyncio
    import datetime
    async def display_date(loop):
        end_time = loop.time() + 5.0
        while True:
            print(datetime.datetime.now())
            if (loop.time() + 1.0) >= end_time:
                break
            await asyncio.sleep(1)
            # asyncio.sleep睡眠指定时间再返回的协程,asyncio中有相应的调度机制
    loop = asyncio.get_event_loop()
    loop.run_until_complete(display_date(loop))
    loop.close()
    
    打印结果

    5. 链式协程

    • compute()协程被print_sum()等待:当compute()被执行完成并返回结果时print_sum()继续执行
    import asyncio
    async def compute(x, y):
        print("Compute %s + %s ..." % (x, y))
        await asyncio.sleep(1.0)
        return x + y
    async def print_sum(x, y):
        result = await compute(x, y)
        print("%s + %s = %s" % (x, y, result))
    loop = asyncio.get_event_loop()
    loop.run_until_complete(print_sum(1, 2))
    loop.close()
    
    执行流程图

    6. async/await 与asyncio

    • David Beazley指出async/await 实际上是异步编程的 API ,人们不应该将async/await等同于asyncio,而应该将asyncio看作是一个利用async/await API 进行异步编程的框架。
    • Python 3.5 协程究竟是个啥

    7. 协程asyncio相关的优秀应用

    • asyncpg -- A fast PostgreSQL Database Client Library for Python/asyncio 一个快速的PostgreSQL数据库的客户端库,3倍于psycopg2。
    • uvloop -- uvloop is a fast, drop-in replacement of the built-in asyncio event loop. uvloop is implemented in Cython and uses libuv under the hood. 内置事件循环器的快速、插入式替代品。
    • aiohttp -- http client/server for asyncio 异步http框架

    相关文章

      网友评论

        本文标题:python-任务和协程文档翻译及延伸

        本文链接:https://www.haomeiwen.com/subject/idwuettx.html