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基础教程之获取本机ip数据包示例
Feb 10 Python
编写Python脚本来实现最简单的FTP下载的教程
May 04 Python
深入浅析Python中join 和 split详解(推荐)
Jun 30 Python
发布你的Python模块详解
Sep 15 Python
Python新手们容易犯的几个错误总结
Apr 01 Python
python并发编程之线程实例解析
Dec 27 Python
详解通过API管理或定制开发ECS实例
Sep 30 Python
在IPython中执行Python程序文件的示例
Nov 01 Python
python语言基本语句用法总结
Jun 11 Python
通过字符串导入 Python 模块的方法详解
Oct 27 Python
Python 实现try重新执行
Dec 21 Python
django序列化时使用外键的真实值操作
Jul 15 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
thinkphp框架下404页面设置 仅三步
2016/05/14 PHP
PHP调用接口API封装的例子
2019/10/11 PHP
PHP7 list() 函数修改
2021/03/09 PHP
JS基础之undefined与null的区别分析
2011/08/08 Javascript
JavaScript高级程序设计(第3版)学习笔记6 初识js对象
2012/10/11 Javascript
js将json格式内容转换成对象的方法
2013/11/01 Javascript
JavaScript中判断两个字符串是否相等的方法
2015/07/07 Javascript
jquery实现滑动特效代码
2015/08/10 Javascript
KnockoutJs快速入门教程
2016/05/16 Javascript
Angular开发者指南之入门介绍
2017/03/05 Javascript
微信小程序实现展示评分结果功能
2019/02/15 Javascript
jQuery中实现text()的方法
2019/04/04 jQuery
记一次Vue.js混入mixin的使用(分权限管理页面)
2019/04/17 Javascript
Vuex 模块化使用详解
2019/07/31 Javascript
vue实现输入框的模糊查询的示例代码(节流函数的应用场景)
2019/09/01 Javascript
Layui多选只有最后一个值的解决方法
2019/09/02 Javascript
24个解决实际问题的ES6代码片段(小结)
2020/02/02 Javascript
react antd表格中渲染一张或多张图片的实例
2020/10/28 Javascript
Python ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍
2014/06/10 Python
python使用requests模块实现爬取电影天堂最新电影信息
2019/04/03 Python
python scrapy爬虫代码及填坑
2019/08/12 Python
django自带调试服务器的使用详解
2019/08/29 Python
python 图像判断,清晰度(明暗),彩色与黑白实例
2020/06/04 Python
HTML5标签使用方法详解
2015/11/27 HTML / CSS
LA MER海蓝之谜美国官网:传奇面霜
2016/08/27 全球购物
百度JavaScript笔试题
2015/01/15 面试题
土木工程专业大学毕业生求职信
2013/10/13 职场文书
社会实践心得体会
2014/01/03 职场文书
产品促销活动策划书
2014/01/15 职场文书
生日寄语大全
2014/04/08 职场文书
青春演讲稿范文
2014/05/08 职场文书
2014年9.18纪念日演讲稿
2014/09/14 职场文书
2014年员工工作总结范文
2014/11/18 职场文书
看古人们是如何赞美老师的?
2019/07/08 职场文书
导游词之日月潭
2019/11/05 职场文书
Win11右下角图标点了没反应怎么办?Win11点击右下角图标无反应解决方法汇总
2022/07/07 数码科技