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 相关文章推荐
Go语言基于Socket编写服务器端与客户端通信的实例
Feb 19 Python
Python设计模式之MVC模式简单示例
Jan 10 Python
Python实现简单http服务器
Apr 12 Python
python中字符串的操作方法大全
Jun 03 Python
Django实现支付宝付款和微信支付的示例代码
Jul 25 Python
python后端接收前端回传的文件方法
Jan 02 Python
Django中使用 Closure Table 储存无限分级数据
Jun 06 Python
在tensorflow下利用plt画论文中loss,acc等曲线图实例
Jun 15 Python
Python 分布式缓存之Reids数据类型操作详解
Jun 24 Python
Django 实现jwt认证的示例
Apr 30 Python
Python pygame实现中国象棋单机版源码
Jun 20 Python
Python可视化神器pyecharts绘制地理图表
Jul 07 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用于页面跳转要注意的几个问题总结
2008/10/03 PHP
php中使用Akismet防止垃圾评论的代码
2011/06/10 PHP
应用开发中涉及到的css和php笔记分享
2011/08/02 PHP
apache mysql php 源码编译使用方法
2012/05/03 PHP
PHP Warning: Module 'modulename' already loaded in问题解决办法
2015/03/16 PHP
PHP获取Exif缩略图的方法
2015/07/13 PHP
Yii框架扩展CGridView增加导出CSV功能的方法
2017/05/24 PHP
PHP一致性hash分布式算法封装类定义与用法示例
2018/08/04 PHP
js 图片缩放(按比例)控制代码
2009/05/27 Javascript
Prototype Object对象 学习
2009/07/12 Javascript
javaScript(JS)替换节点实现思路介绍
2013/04/17 Javascript
JavaScript获取和设置CheckBox状态的简单方法
2013/07/05 Javascript
JS 打印界面的CSS居中代码适用所有浏览器
2014/03/19 Javascript
jQuery制作拼图小游戏
2015/01/12 Javascript
Js实现自定义右键行为
2015/03/26 Javascript
AngularJS 获取ng-repeat动态生成的ng-model值实例详解
2016/11/29 Javascript
微信小程序实现缓存根据不同的id来进行设置和读取缓存
2017/06/12 Javascript
react-native-fs实现文件下载、文本存储的示例代码
2017/09/22 Javascript
vue+node+webpack环境搭建教程
2017/11/05 Javascript
jquery+css3实现熊猫tv导航代码分享
2018/02/12 jQuery
Vue.js 2.0和Cordova开发webApp环境搭建方法
2018/02/26 Javascript
layer.confirm取消按钮绑定事件的方法
2018/08/17 Javascript
vue动画效果实现方法示例
2019/03/18 Javascript
vue搜索和vue模糊搜索代码实例
2019/05/07 Javascript
Python类的基础入门知识
2008/11/24 Python
深入理解NumPy简明教程---数组1
2016/12/17 Python
python实现简单登陆流程的方法
2018/04/22 Python
Python urlopen()和urlretrieve()用法解析
2020/01/07 Python
HTML5中微数据概述及在搜索引擎中的使用举例
2013/02/07 HTML / CSS
Zavvi美国:英国娱乐之家
2017/03/19 全球购物
Hush Puppies澳大利亚官网:舒适的男女休闲和正装鞋
2019/08/24 全球购物
家长通知书教师评语
2014/04/17 职场文书
医药公司开票员岗位职责
2015/04/15 职场文书
阳光体育运动标语口号
2015/12/26 职场文书
python脚本框架webpy模板控制结构
2021/11/20 Python
详解NumPy中的线性关系与数据修剪压缩
2022/05/25 Python