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 相关文章推荐
pycharm 使用心得(二)设置字体大小
Jun 05 Python
Python中functools模块函数解析
Mar 12 Python
Pycharm编辑器技巧之自动导入模块详解
Jul 18 Python
python简单商城购物车实例代码
Mar 15 Python
Python3之读取连接过的网络并定位的方法
Apr 22 Python
Django实现全文检索的方法(支持中文)
May 14 Python
Python玩转PDF的各种骚操作
May 06 Python
Python3列表内置方法大全及示例代码小结
May 10 Python
python numpy实现文件存取的示例代码
May 26 Python
简单了解Pandas缺失值处理方法
Nov 16 Python
python文件绝对路径写法介绍(windows)
Dec 25 Python
Python3 pyecharts生成Html文件柱状图及折线图代码实例
Sep 29 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面向对象全攻略 (十二) 抽象方法和抽象类
2009/09/30 PHP
利用PHP扩展vld查看PHP opcode操作步骤
2013/03/04 PHP
php读取富文本的时p标签会出现红线是怎么回事
2014/05/13 PHP
ThinkPHP中自定义错误页面和提示页面实例
2014/11/22 PHP
Laravel 修改验证异常的响应格式实例代码详解
2020/05/25 PHP
用js实现手把手教你月入万刀(转贴)
2007/11/07 Javascript
JavaScript入门教程(11) js事件处理
2009/01/31 Javascript
解决node-webkit 不支持html5播放mp4视频的方法
2015/03/11 Javascript
JS获取及设置TextArea或input文本框选择文本位置的方法
2015/03/24 Javascript
如何用angularjs制作一个完整的表格
2016/01/21 Javascript
超实用的JavaScript表单代码段
2016/02/26 Javascript
第一次接触JS require.js模块化工具
2016/04/17 Javascript
jquery css实现邮箱自动补全
2016/11/14 Javascript
微信小程序 setData的使用方法详解
2017/04/20 Javascript
详解vue过滤器在v2.0版本用法
2017/06/01 Javascript
Vue ElementUi同时校验多个表单(巧用new promise)
2018/06/06 Javascript
JS实现的tab页切换效果完整示例
2018/12/18 Javascript
使用ESLint禁止项目导入特定模块的方法步骤
2019/03/04 Javascript
vue实现移动端返回顶部
2020/10/12 Javascript
Python中使用logging模块打印log日志详解
2015/04/05 Python
python爬虫 正则表达式使用技巧及爬取个人博客的实例讲解
2017/10/20 Python
Python多线程threading模块用法实例分析
2019/05/22 Python
Python创建或生成列表的操作方法
2019/06/19 Python
python pytest进阶之xunit fixture详解
2019/06/27 Python
在Python3 numpy中mean和average的区别详解
2019/08/24 Python
css3通过scale()、rotate()实现放大、旋转
2020/03/19 HTML / CSS
AE美国鹰美国官方网站:American Eagle Outfitters
2016/08/22 全球购物
入党申请书自我鉴定
2013/10/12 职场文书
函授大专自我鉴定
2013/11/01 职场文书
学校先进集体事迹材料
2014/05/31 职场文书
坚守艰苦奋斗精神坚决反对享乐主义整改措施
2014/09/17 职场文书
公安民警正风肃纪剖析材料
2014/10/10 职场文书
合作合同协议书范本
2015/01/27 职场文书
部门经理助理岗位职责
2015/04/13 职场文书
2015年超市收银员工作总结
2015/04/25 职场文书
MongoDB数据库常用的10条操作命令
2021/06/18 MongoDB