asyncio 的 coroutine对象 与 Future对象使用指南


Posted in Python onSeptember 11, 2016

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)

将异常转换为正常的结果返回。

Python 相关文章推荐
Python的Tornado框架的异步任务与AsyncHTTPClient
Jun 27 Python
Python编程中对super函数的正确理解和用法解析
Jul 02 Python
Python 中 Virtualenv 和 pip 的简单用法详解
Aug 18 Python
win10下tensorflow和matplotlib安装教程
Sep 19 Python
用Python编写一个高效的端口扫描器的方法
Dec 20 Python
Python学习笔记之抓取某只基金历史净值数据实战案例
Jun 03 Python
使用python爬取抖音视频列表信息
Jul 15 Python
Django Rest framework认证组件详细用法
Jul 25 Python
python 求定积分和不定积分示例
Nov 20 Python
Python3并发写文件与Python对比
Nov 20 Python
Python 实现opencv所使用的图片格式与 base64 转换
Jan 09 Python
Python self用法详解
Nov 28 Python
Python中使用asyncio 封装文件读写
Sep 11 #Python
Python 如何访问外围作用域中的变量
Sep 11 #Python
Python优化技巧之利用ctypes提高执行速度
Sep 11 #Python
Python 中的with关键字使用详解
Sep 11 #Python
Python冒泡排序注意要点实例详解
Sep 09 #Python
通过5个知识点轻松搞定Python的作用域
Sep 09 #Python
python验证码识别的实例详解
Sep 09 #Python
You might like
php 图片加水印与上传图片加水印php类
2010/05/12 PHP
PHP 小心urldecode引发的SQL注入漏洞
2011/10/27 PHP
php实现cc攻击防御和防止快速刷新页面示例
2014/02/13 PHP
推荐一本PHP程序猿都应该拜读的书
2014/12/31 PHP
PHP实现将浏览历史页面网址保存到cookie的方法
2015/01/26 PHP
PHP Warning: Module 'modulename' already loaded in问题解决办法
2015/03/16 PHP
js location.replace与location.reload的区别
2010/09/08 Javascript
node.js中EJS 模板快速入门教程
2017/05/08 Javascript
使用 Vue.js 仿百度搜索框的实例代码
2017/05/09 Javascript
JS利用正则表达式实现简单的密码强弱判断实例
2017/06/16 Javascript
VUE饿了么树形控件添加增删改功能的示例代码
2017/10/17 Javascript
node学习笔记之读写文件与开启第一个web服务器操作示例
2019/05/29 Javascript
AntV F2和vue-cli构建移动端可视化视图过程详解
2019/10/08 Javascript
VUE 解决mode为history页面为空白的问题
2019/11/01 Javascript
vue 中的动态传参和query传参操作
2020/11/09 Javascript
[00:10]DOTA2全国高校联赛速递
2018/05/30 DOTA
python使用递归解决全排列数字示例
2014/02/11 Python
Python模拟百度登录实例详解
2016/01/20 Python
以一个投票程序的实例来讲解Python的Django框架使用
2016/02/18 Python
python爬取w3shcool的JQuery课程并且保存到本地
2017/04/06 Python
python爬取亚马逊书籍信息代码分享
2017/12/09 Python
Linux下通过python获取本机ip方法示例
2019/09/06 Python
python3实现elasticsearch批量更新数据
2019/12/03 Python
大学四年规划书范文
2013/12/27 职场文书
上班玩游戏检讨书
2014/02/07 职场文书
企业业务员岗位职责
2014/03/14 职场文书
房地产推广策划方案
2014/05/19 职场文书
春节超市活动方案
2014/08/14 职场文书
投标文件签署授权委托书范本
2014/10/12 职场文书
领导班子整改方案
2014/10/25 职场文书
2014年技术部工作总结
2014/12/12 职场文书
2014年后勤工作总结范文
2014/12/16 职场文书
2014年骨干教师工作总结
2014/12/19 职场文书
小学少先队工作总结2015
2015/05/26 职场文书
2015年学校精神文明工作总结
2015/05/27 职场文书
同意报考公务员证明
2015/06/17 职场文书