ing coro=<main() running at 1-2-1.py:21> wait_for=<Task pending coro=<nested() running at 1-2-1.py:10> wait_for=<Future cancelled> cb=[<TaskWakeupMethWrapper object at 0x10d342918>()]>> <Task pending coro=<nested() running at 1-2-1.py:10> wait_for=<Future cancelled> cb=[<TaskWakeupMethWrapper object at 0x10d342918>()]> <Task cancelling coro=<nested() running at 1-2-1.py:10> wait_for=<Future cancelled> cb=[<TaskWakeupMethWrapper object at 0x10d342918>()]>
因为我们调用了task.cancel() 所以可以看到此时的任务状态为取消状态。
并发的执行任务
通过使用await+asyncio.gather可以完成并发的操作。
asyncio.gather用法如下。
**asyncio.gather(*aws, loop=None, return_exceptions=False)
aws是一系列协程,协程都成功完成,就返回值一个结果列表。结果值的顺序与aws中添加协程的顺序相对应。
return_exceptions=False,其实就是如果有一个任务失败了,就直接抛出异常。如果等于True就把错误信息作为结果返回回来。
首先来一个正常情况不出错的例子:
import asyncio async def factorial(name, number): f = 1 for i in range(2, number + 1): print(f"Task {name}: Compute factorial({i})...") if number == 2: 1 / 0 await asyncio.sleep(1) f *= i print(f"Task {name}: factorial({number}) = {f}") async def main():
输入以下内容:
Task A: Compute factorial(2)... Task B: Compute factorial(2)... Task C: Compute factorial(2)... Task B: Compute factorial(3)... Task C: Compute factorial(3)... Task B: factorial(3) = 6 Task C: Compute factorial(4)... Task C: factorial(4) = 24 division by zero None None
可以发现async.gather最后会返回一系列的结果,如果出现了错误就把错误信息作为返回结果,这里我当数字为2时人为加了异常操作1/0,于是返回了结果division by zero,对于其他的任务因为没有返回值所以是None。这里return_exceptions=True来保证了如果其中一个任务出现异常,其他任务不会受其影响会执行到结束。
asyncio.wait
coroutine asyncio.wait(aws, *, loop=None, timeout=None, return_when=ALL_COMPLETED)
asyncio.wait和async.gather用法差不多只是async.wait接收的是个列表。
第三个参数和async.gather有点区别.
FIRST_COMPLETED |
任何一个future完成或取消时返回 |
FIRST_EXCEPTION |
任何一个future出现错误将返回,如果出现异常等价于ALL_COMPLETED |
ALL_COMPLETED |
当所有任务完成或者被取消时返回结果,默认值。 |
Timeouts
通过使用asyncio.wait_for来完成一个超时函数回调操作,如果函数规定时间内未完成则报错。
**asyncio.wait_for(aw, timeout, *, loop=None)**
aw代表一个协程,timeout单位秒。
async def eternity():
1秒内eternity没有完成就报错了。
python3.7中发生更改:当aw由于超时而被取消时,不再显示异常而是等待aw被取消。
说到timeout的,如果仅仅是对一个代码块做timeout操作而不是等待某个协程此时推荐第三方模块async_timeout
async_timeout
安装
pip installa async_timeout
使用方法很简单如下
async with async_timeout.timeout(1.5) as cm: await inner() print(cm.expired)
如果1.5s可以运行完打印true,否则打印false,表示超时。
asyncio.as_completed
**asyncio.as_completed(aws, *, loop=None, timeout=None)**
使用as_completed会返回一个可以迭代的future对象,同样可以获取协程的运行结果,使用方法如下:
async def main(): coroutine1 = do_some_w