asyncio异步IO--协程(Coroutine)与任务(Task)详解 (5)

执行结果如下:

Start at: 17:19:11 delay for 0 seconds. delay for 1 seconds. delay for 2 seconds. delay for 3 seconds. delay for 4 seconds. delay for 5 seconds. delay for 6 seconds. delay for 7 seconds. delay for 8 seconds. delay for 9 seconds. End at: 17:19:20 从其他线程调度执行(Scheduling From Other Threads) asyncio.run_coroutine_threadsafe(coro,loop)

向loop指定的事件循环提交一个由coro指定协程。线程安全。
返回一个concurrent.futures.Future对象,等待另一个线程返回结果。
这个函数用于从当前线程向运行事件循环的线程提交协程(coroutine)。
例如:

# Create a coroutine coro = asyncio.sleep(1, result=3) # Submit the coroutine to a given loop future = asyncio.run_coroutine_threadsafe(coro, loop) # Wait for the result with an optional timeout argument assert future.result(timeout) == 3

如果协程出现异常,返回的Future会收到通知。返回的Future也可以被用作取消事件循环中的任务:

try: result = future.result(timeout) except asyncio.TimeoutError: print('The coroutine took too long, cancelling the task...') future.cancel() except Exception as exc: print(f'The coroutine raised an exception: {exc!r}') else: print(f'The coroutine returned: {result!r}')

可以参考章节。
与其他asyncio函数不同,该函数需要 显式 传递loop参数。
新增于Python 3.5.1

自查(Introspection) current_task() asyncio.current_task(loop=None)

返回事件循环中正在运行的Task实例,如果没有Task在执行,则返回None。
如果loop为None,则使用get_running_loop()获取当前事件循环。
新增于Python3.7

all_tasks() asyncio.all_tasks(loop=None)

返回事件循环中尚未运行结束的Task对象集合。
如果loop为None,则,使用get_running_loop()获取当前事件循环。
新增于Python3.7

Task对象 class asyncio.Task(coro,*,loop=None)

类似与Future对象,用于执行Python协程。非线程安全。
Tasks用于在事件循环中执行协程。如果协程等待一个Future,那么Task会暂停协程的执行,直到Future执行完成。当Future完成时,协程的执行会恢复。
事件循环的 协作调度 模式:一个事件循环同一时间只执行一个Task。当这个Task等待某个Future返回时,事件循环执行其他的Task、回调或IO操作。

可以通过高层函数asyncio.create_task()创建Task,或者通过底层函数loop.create_task()和ensure_future()创建Task。但是不建议直接实例化Task对象。

如果想要取消一个Task的执行,可以使用cancel()方法。调用cancel()会引起Task对象向被封装的协程抛出CancelledError异常。当取消行为发生时,如果协程正在等待某个Future对象执行,该Future对象将被取消。

cancelled()方法用于检查某个Task是否已被取消。如果Task封装的协程没有阻止CancelledError异常,且Task确实被取消了,则该方法返回True。

asyncio.Task继承了Future类中除Future.set_result()和Future.set_exception()以外的所有方法。

Task对象支持contextvars模块:当一个Task被创建的时候,它会复制当前的上下文,然后在复制的上下文副本中执行协程。

Python3.7中的变更:添加了对contextvars模块的支持。

cancel()

申请取消任务。
将在下一个事件循环周期中将CancelledError异常抛给封装在Task中的协程。
收到CancelledError异常后,协程有机会处理异常,甚至以try ...except CancelledError ...finally来拒绝请求。因此,与Future.cancel()不同,Task.cancel()不能保证Task一定被取消掉。当然,拒绝取消请求这种操作并不常见,而且很不提倡。

以下例子可以说明协程如何拦截取消请求:

import asyncio async def cancel_me(): print('cancel_me(): before sleep') try: # Wait for 1 hour await asyncio.sleep(3600) except asyncio.CancelledError: print('cancel_me(): cancel sleep') raise finally: print('cancel_me(): after sleep') async def main(): # Create a "cancel_me" Task task = asyncio.create_task(cancel_me()) # Wait for 1 second await asyncio.sleep(1) task.cancel() try: await task except asyncio.CancelledError: print("main(): cancel_me is cancelled now") asyncio.run(main()) # Expected output: # # cancel_me(): before sleep # cancel_me(): cancel sleep # cancel_me(): after sleep # main(): cancel_me is cancelled now cancelled()

如果Task已经被取消,则返回True。
当取消请求通过cancel()被提交,且Task封装的协程传播了抛给它的CancelledError异常,则此Task被取消。

done()

如果Task已完成,则返回True。
Task完成有三种情况:

封装的协程已返回

封装的协程已抛出异常

Task被取消

result()

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzspx.html