您好,欢迎访问一九零五行业门户网

详解asyncio的coroutine对象与Future对象使用方法

asyncio是python 3.4版本引入的标准库,直接内置了对异步io的支持。asyncio的编程模型就是一个消息循环。今天我们就来详细讨论下asyncio 中的 coroutine 与 future对象
>
coroutine 与 future 的关系
看起来两者是一样的,因为都可以用以下的语法来异步获取结果,
result = await future result = await coroutine
实际上,coroutine 是生成器函数,它既可以从外部接受参数,也可以产生结果。使用 coroutine 的好处是,我们可以暂停一个函数,然后稍后恢复执行。比如在涉及到网路操作的情况下,能够停下函数直到响应到来。在停下的这段时间内,我们可以切换到其他任务继续执行。
而 future 更像是 javascript 中的 promise 对象。它是一个占位符,其值会在将来被计算出来。在上述的例子中,当我们在等待网络 io 函数完成时,函数会给我们一个容器,promise 会在完成时填充该容器。填充完毕后,我们可以用回调函数来获取实际结果。
task 对象是 future 的子类,它将 coroutine 和 future 联系在一起,将 coroutine 封装成一个 future 对象。
一般会看到两种任务启动方法,
tasks = asyncio.gather(   asyncio.ensure_future(func1()),   asyncio.ensure_future(func2()) ) loop.run_until_complete(tasks)

tasks = [   asyncio.ensure_future(func1()),   asyncio.ensure_future(func2())   ] loop.run_until_complete(asyncio.wait(tasks))
ensure_future 可以将 coroutine 封装成 task。asyncio.gather 将一些 future 和 coroutine 封装成一个 future。
asyncio.wait 则本身就是 coroutine。
run_until_complete 既可以接收 future 对象,也可以是 coroutine 对象,
baseeventloop.run_until_complete(future) run until the future is done. if the argument is a coroutine object, it is wrapped by ensure_future(). return the future's result, or raise its exception.
task 任务的正确退出方式
在 asyncio 的任务循环中,如果使用 ctrl-c 退出的话,即使捕获了异常,event loop 中的任务会报错,出现如下的错误,
task was destroyed but it is pending!
task: <task pending coro=<kill_me() done, defined at test.py:5> wait_for=<future pending cb=[task._wakeup()]>>
根据官方文档,task 对象只有在以下几种情况,会认为是退出,
a result / exception are available, or that the future was cancelled
task 对象的 cancel 和其父类 future 略有不同。当调用 task.cancel() 后,对应 coroutine 会在事件循环的下一轮中抛出 cancellederror 异常。使用 future.cancelled() 并不能立即返回 true(用来表示任务结束),只有在上述异常被处理任务结束后才算是 cancelled。
故结束任务可以用
for task in asyncio.task.all_tasks():   task.cancel()
这种方法将所有任务找出并 cancel。
但 ctrl-c 也会将事件循环停止,所以有必要重启事件循环,
try:   loop.run_until_complete(tasks) except keyboardinterrupt as e:   for task in asyncio.task.all_tasks():     task.cancel()   loop.run_forever() # restart loop finally:   loop.close()
在每个 task 中捕获异常是必要的,如果不确定,可以使用
asyncio.gather(..., return_exceptions=true)
将异常转换为正常的结果返回。
以上就是详解asyncio的coroutine对象与future对象使用方法的详细内容。
其它类似信息

推荐信息