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 自动提交和抓取网页
Jul 13 Python
Python操作Redis之设置key的过期时间实例代码
Jan 25 Python
python3 requests中使用ip代理池随机生成ip的实例
May 07 Python
简单了解python反射机制的一些知识
Jul 13 Python
python tkinter控件布局项目实例
Nov 04 Python
pygame实现烟雨蒙蒙下彩虹雨
Nov 11 Python
Python如何使用内置库matplotlib绘制折线图
Feb 24 Python
Python reversed函数及使用方法解析
Mar 17 Python
tensorflow使用CNN分析mnist手写体数字数据集
Jun 17 Python
详解pycharm的python包opencv(cv2)无代码提示问题的解决
Jan 29 Python
详解Python牛顿插值法
May 11 Python
python在package下继续嵌套一个package
Apr 14 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
PHP4实际应用经验篇(8)
2006/10/09 PHP
php的list()的一步操作给一组变量进行赋值的使用
2011/05/18 PHP
PHP微信开发之文本自动回复
2016/06/23 PHP
PHP正则判断一个变量是否为正整数的方法
2019/02/27 PHP
Jquery 复选框取值兼容FF和IE8(测试有效)
2013/10/29 Javascript
Jquery 过滤器(first,last,not,even,odd)的使用
2014/01/22 Javascript
extJS中常用的4种Ajax异步提交方式
2014/03/07 Javascript
JQuery调用WebServices的方法和4个实例
2014/05/06 Javascript
js实现无缝滚动特效
2015/12/20 Javascript
JavaScript对象数组排序函数及六个用法
2015/12/23 Javascript
JavaScript获取当前url根目录(路径)
2016/06/17 Javascript
深入理解Javascript中的valueOf与toString
2017/01/04 Javascript
bootstrap css样式之表单
2017/01/19 Javascript
vue打包后显示空白正确处理方法
2017/11/01 Javascript
使用puppeteer破解极验的滑动验证码
2018/02/24 Javascript
Angular使用ControlValueAccessor创建自定义表单控件
2019/03/08 Javascript
基于vue实现一个禅道主页拖拽效果
2019/05/27 Javascript
Vue实现滑动拼图验证码功能
2019/09/15 Javascript
node.js实现简单的压缩/解压缩功能示例
2019/11/05 Javascript
[02:37]2018DOTA2亚洲邀请赛赛前采访-EG篇
2018/04/03 DOTA
[52:52]完美世界DOTA2联赛PWL S3 LBZS vs access 第一场 12.10
2020/12/13 DOTA
python 装饰器功能以及函数参数使用介绍
2012/01/27 Python
Python使用defaultdict读取文件各列的方法
2017/05/11 Python
python3之微信文章爬虫实例讲解
2017/07/12 Python
利用selenium 3.7和python3添加cookie模拟登陆的实现
2017/11/20 Python
python使用锁访问共享变量实例解析
2018/02/08 Python
python中subprocess批量执行linux命令
2018/04/27 Python
利用Python半自动化生成Nessus报告的方法
2019/03/19 Python
Python深拷贝与浅拷贝用法实例分析
2019/05/05 Python
如何在mac环境中用python处理protobuf
2019/12/25 Python
Pretty You London官网:英国拖鞋和睡衣品牌
2019/05/08 全球购物
杠杆的科学教学反思
2014/01/10 职场文书
英语四级考试作弊检讨书
2014/09/29 职场文书
生产车间主任岗位职责
2015/04/08 职场文书
2015年售后服务工作总结
2015/04/25 职场文书
《追风筝的人》:人心中的成见是座大山,但请不忘初心
2019/11/15 职场文书