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 Trie树实现字典排序
Mar 28 Python
简单的抓取淘宝图片的Python爬虫
Dec 25 Python
Python Property属性的2种用法
Jun 21 Python
Python获取央视节目单的实现代码
Jul 25 Python
使用tensorflow实现AlexNet
Nov 20 Python
python3+PyQt5实现自定义分数滑块部件
Apr 24 Python
numpy中的ndarray方法和属性详解
May 27 Python
Python3安装pip工具的详细步骤
Oct 14 Python
python中with语句结合上下文管理器操作详解
Dec 19 Python
Tensorflow读取并输出已保存模型的权重数值方式
Jan 04 Python
Python关键字及可变参数*args,**kw原理解析
Apr 04 Python
appium+python自动化配置(adk、jdk、node.js)
Nov 17 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 header下载函数
2014/01/31 PHP
Laravel中基于Artisan View扩展包创建及删除应用视图文件的方法
2016/10/08 PHP
PHP进程通信基础之信号量与共享内存通信
2017/02/19 PHP
ThinkPHP 框架实现的读取excel导入数据库操作示例
2020/04/14 PHP
Javascript 布尔型分析
2008/12/22 Javascript
ie与ff下的event事件使用介绍
2013/11/25 Javascript
jQuery中:first-child选择器用法实例
2014/12/31 Javascript
Javascript基础教程之while语句
2015/01/18 Javascript
基于Bootstrap实现图片轮播效果
2016/05/22 Javascript
纯js和css完成贪吃蛇小游戏demo
2016/09/01 Javascript
layer弹窗插件操作方法详解
2017/05/19 Javascript
[js高手之路]设计模式系列课程-发布者,订阅者重构购物车的实例
2017/08/29 Javascript
vue实现商城上货组件简易版
2017/11/27 Javascript
JavaScript判断变量名是否存在数组中的实例
2017/12/28 Javascript
微信小程序实现的自定义分享功能示例
2019/02/12 Javascript
vue 进阶之实现父子组件间的传值
2019/04/26 Javascript
js对象简介与基本用法示例
2020/03/13 Javascript
Ant Design的可编辑Tree的实现操作
2020/10/31 Javascript
[27:39]Ti4 循环赛第二日 LGD vs Fnatic
2014/07/11 DOTA
[02:28]DOTA2亚洲邀请赛 LGD战队巡礼
2015/02/03 DOTA
python3.4用函数操作mysql5.7数据库
2017/06/23 Python
详解用TensorFlow实现逻辑回归算法
2018/05/02 Python
python-itchat 统计微信群、好友数量,及原始消息数据的实例
2019/02/21 Python
Python利用lxml模块爬取豆瓣读书排行榜的方法与分析
2019/04/15 Python
pandas 对日期类型数据的处理方法详解
2019/08/08 Python
解决pycharm中的run和debug失效无法点击运行
2020/06/09 Python
详解python tcp编程
2020/08/24 Python
python中pdb模块实例用法
2021/01/15 Python
优秀志愿者事迹材料
2014/02/03 职场文书
计算机网络专业自荐信
2014/07/04 职场文书
家庭贫困证明范本(经典版)
2014/09/22 职场文书
工程服务质量承诺书
2015/04/29 职场文书
2019行政前台转正申请书范文3篇
2019/08/15 职场文书
Pytorch中TensorBoard及torchsummary的使用详解
2021/05/12 Python
css height属性中的calc方法详解
2021/06/03 HTML / CSS
在js中修改html body的样式
2021/11/11 Javascript