学习python异步编程asyncio之协程和任务
Awaitables
- 定义: 如果一个对象可以在 await 表达式中被使用的话,那么这就是一个可等待的对象(awaitable object).
- 三种可等待的对象: 协程coroutines, 任务Tasks 和 期望Futures.
协程 coroutines
- 协程函数:一个由async def 定义的函数。
- 协程对象: 通过调用协程函数所返回的对象。
- python协程都是可等待的(awaitable),他们也能在其它协程中被等待。在某一个协程中, 如果不加 await关键字,只是普通调用另一个协程的话,不会执行任何东西。
- 执行协程的三种方法:
- 使用await 关键字,如:
await asyncio.sleep
- 使用
asyncio.run()
执行顶层入口函数。 - 使用
asyncio.create_task()
将协程包装为任务,再用await 关键字。
- 使用await 关键字,如:
任务Tasks
- 用于并发编排协程。
- 使用
task = asyncio.create_task()
将一个协程包装成任务, 此函数返回Task。 - task可以被取消, 也可以使用
await task
等待其完成。
期望Futures
- 定义: 一种特殊的低层次可等待对象,用来表示一个异步操作的最终结果。
- 一般来说无需在应用程序代码中显式创建Futures。
相关函数调用
asyncio.run(coro, *, debug=False)
- 此调用将执行传入的协程并返回结果,管理asyncio事件循环, 最终确定异步生成器, 并关闭线程池。
- 当同一线程中已经有一个正在运行的asyncio事件循环,则此调用不可用。
- debug 设为
True
, 则事件循环将在调试模式下运行。 - 此调用会创建一个新的事件循环并在最后将其关闭。应该将其用作asyncio程序的主入口,且只调用一次。
asyncio.create_task(coro, *, name=None)
- 返回Task对象,并安排协程coro的执行。
- 此调用将在get_running_loop() 所返回的事件循环中执行。
- python 3.7之前版本请使用asyncio.ensure_future()
asyncio.sleep(delay, result=None)
- 没啥可说的
awaitable asyncio.gather(*aws, return_exceptions=False)
- 以传入的aws中的顺序, 并发执行awaitable。
- aws中的任何协程都会被自动安排为任务Task。
- 默认抛出第一个异常, 但其它awaitable不会被取消而是继续执行。
awaitable asyncio.shield(aw)
- 使awaitable免于被取消
- aw 若是协程,则被自动安排为任务Task。
res = await shield(something())
等价于res = await something()
,唯一的区别是,如果包含这条语句的协程被取消,something()
中跑着的Task不会被取消。对于something()
来说,取消从未发生过。
coroutine asyncio.wait_for(aw, timeout)
- 设置 awaitable的超时时限。
asyncio.wait(aws, *, timeout=None, return_when=ALL_COMPLETED)
- 并发执行aws中所有的awaitable, 在满足return_when指定的条件之前,将一直阻塞。
- 返回值是 Futures 或 Tasks的集合:
done, pending = await asyncio.wait(aws)
. - 如果设置timeout,则超时的Futures 或 Tasks 会被返回到pending 中
- return_when 有三种可选值:
FIRST_COMPLETED
,FIRST_EXCEPTION
,ALL_COMPLETED
.
asyncio.as_completed(aws, *, timeout=None)
- 返回协程的迭代器
参考
https://docs.python.org/3/library/asyncio-task.html#coroutine