当前位置 : 主页 > 编程语言 > python >

Future与Task

来源:互联网 收集:自由互联 发布时间:2022-06-15
​​Tasks and coroutines​​ 翻译的python官方文档 这个问题的恶心之处在于,如果你要理解​​coroutine​​​,你应该理解​​future​​​和​​task​​​。而你如果想理解​​future​​


​​Tasks and coroutines​​

翻译的python官方文档

这个问题的恶心之处在于,如果你要理解​​coroutine​​​,你应该理解​​future​​​和​​task​​​。而你如果想理解​​future​​​和​​task​​​你应该先理解​​coroutine​​。所以在第一遍阅读官方文档的时候,感觉完全是在梦游。但读到第二遍和第三遍的时候,就清楚很多了。

Coroutines

协程(​​coroutine​​)包括两个概念:

  • 协程函数(​​async def​​​ 或者​​@asyncio.coroutine​​)
  • 协程函数所返回的协程对象。
  • 协程功能:

  • 通过​​result = await future​​​或者​​result = yeild from future​​​,悬挂协程,直到​​future​​​完成,获取​​future​​​的结果/异常(参见下面对​​future​​​及​​future​​​结果的描述,或等看完​​future​​之后回来再阅读这一段)。
  • 通过​​result = await coroutine​​​ 或者​​result = yeild from coroutine​​ 等待另一个协程的结果(或者异常,异常会被传播)。
  • ​​returen expression​​​ 返回该协程的结果,被​​await​​​,或者​​yield from​​获取。
  • ​​raise exception​​​,抛出异常,被​​await​​​,或者​​yield from​​获取。
  • 调用协程函数并不能使该协程运行。调用协程函数所返回的协程对象,在被你安排执行之前,不会做任何事情。有两种方式可以启动它:

  • 通过在一个已经启动的协程中调用:​​await coroutine​​​或者​​yield from coroutine​​
  • 或者通过​​ensure_task()​​​以及​​loop.create_task()​​安排协程的执行。
  • 只有事件循环在运行的时候,协程才能运行


    在本文档中,有些普通函数返回了一个​​future​​,也被标记为​​coroutine​​。这是故意的,这样以后就可以自由使用这些函数。如果是在回调代码中使用这个函数,用​​ensure_future​​包装他。


    hello_world.py

    import asyncio

    # 创建一个协程
    async def hello_world():
    print("Hello World!")

    loop = asyncio.get_event_loop()
    # Blocking call which returns when the hello_world() coroutine is done
    # 在事件循环中调用这个协程
    # 不过这里只有一个协程,而其不阻塞
    loop.run_until_complete(hello_world())
    loop.close()

    hello_world2.py

    # 这段代码和上面的代码执行结果是相同的。只不过用了另一种调用协程的方式
    # 先在loop.call_soon()中安排好,再通过loop.run_forever()调用
    # 注意,这里在hello_world中,调用了loop.stop(),否则事件循环就不会终止。
    import asyncio

    def hello_world(loop):
    print('Hello World')
    loop.stop()

    loop = asyncio.get_event_loop()

    # Schedule a call to hello_world()
    loop.call_soon(hello_world, loop)

    # Blocking call interrupted by loop.stop()
    loop.run_forever()
    loop.close()

    Future与Task_赋值


     注意这里​​return 1+2​​​,实际上是​​raise StopIteration(3)​​协程其实是在不停返回结果的。最后的结果才会被返回。

    future

    ​​future​​​是一个容器,或者占位符(placeholder),用于接受异步的结果。这里指的是​​asyncio.Future​​​而不是​​coroutines.futures.Future​​。

    接口

    ​​result()​​

    返回future的结果

    ​​set_result()​​

    指示future已结束,并赋值。注意,必须显式地调用这个接口,才能给future赋值。


    import asyncio

    # 一个对future进行赋值的函数
    async def slow_operation(future):
    await asyncio.sleep(1)
    # 给future赋值
    future.set_result('Future is done!')

    loop = asyncio.get_event_loop()
    # 创建一个future
    future1 = asyncio.Future()
    # 使用ensure_future 创建Task
    asyncio.ensure_future(slow_operation(future1))
    future2 = asyncio.Future()
    asyncio.ensure_future(slow_operation(future2))
    # gather Tasks,并通过run_uniti_complete来启动、终止loop
    loop.run_until_complete(asyncio.gather(future1, future2))
    print(future1.result())
    print(future2.result())
    loop.close()

    如果我们注释掉`future.set_result('Future is done!')一行,这个程序将永远不会结束。

    TASK

    将一个协程的执行过程安排好:用一个​​future​​​包装起来。​​Task​​​是​​Future​​的一个子类。

    ​​Task​​​ 负责在实现循环中执行一个协程。 如果被包装的协程由一个​​future​​​产生,​​task​​​会暂停被包装协程的执行,等待​​future​​​的完成。当​​future​​​完成时,被包装协程会重启,当​​future​​结果/异常返回。

    事件循环使用协同调度:事件循环每次只能执行1个操作。其他​​task​​​可以在别的线程的事件循环中执行。当​​task​​​等待​​future​​​完成时,事件循环会执行一个新的​​task​​。

    取消​​task​​​与取消​​future​​​不同。调用​​cancel()​​​将会向被包装的协程抛出​​CacelledError​​​。如果被包装协程没有捕获​​CacelledError​​​或者抛出​​CancelledError​​​时, ​​cancelled()​​​才返回​​True​​

    太长了,我就不翻译了大意就是说,虽然​​task​​​的​​cancel()​​​函数,只会向被包装协程发出抛出一个异常,但是​​task​​​是否真的​​canceled​​取决于被包装协程如何处理这个异常。

    不要直接创建​​task​​​实例,使用​​ensure_future()​​​函数或者​​loop.create_task()​​方法。

    任务相关函数

    ​​asyncio.ensure_future​​

    安排协程的执行。用future包装它,返回一个task。

    ​​asyncio.gather(*coros_or_futures, loop=None, return_exceptions=False)​​

    将多个协程或future,集成为一个future。
    所有的future必须在一个事件循环中。如果所有的future都成功完成了,则按照输入顺序(而不是返回顺序)返回所有result。

    ​​asyncio.sleep(delay, result=None, *, loop=None)​​

    sleep函数,注意,是可以返回结果的



    上一篇:sorted排序
    下一篇:没有了
    网友评论