Python中使用asyncio 封装文件读写


Posted in Python onSeptember 11, 2016

前言

和网络 IO 一样,文件读写同样是一个费事的操作。

默认情况下,Python 使用的是系统的阻塞读写。这意味着在 asyncio 中如果调用了

f = file('xx')
f.read()

会阻塞事件循环。

本篇简述如何用 asyncio.Future 对象来封装文件的异步读写。

代码在 GitHub。目前仅支持 Linux。

阻塞和非阻塞

首先需要将文件的读写改为非阻塞的形式。在非阻塞情况下,每次调用 read 都会立即返回,如果返回值为空,则意味着文件操作还未完成,反之则是读取的文件内容。

阻塞和非阻塞的切换与操作系统有关,所以本篇暂时只写了 Linux 版本。如果有过 Unix 系统编程经验,会发现 Python 的操作是类似的。

flag = fcntl.fcntl(self.fd, fcntl.F_GETFL) 
if fcntl.fcntl(self.fd, fcntl.F_SETFL, flag | os.O_NONBLOCK) != 0: 
  raise OSError()

Future 对象

Future 对象类似 Javascript 中的 Promise 对象。它是一个占位符,其值会在将来被计算出来。我们可以使用

result = await future

在 future 得到值之后返回。而使用

future.set_result(xxx)

就可以设置 future 的值,也意味着 future 可以被返回了。await 操作符会自动调用 future.result() 来得到值。

loop.call_soon

通过 loop.call_soon 方法可以将一个函数插入到事件循环中。

至此,我们的异步文件读写思路也就出来了。通过 loop.call_soon 调用非阻塞读写文件的函数。若一次文件读写没有完成,则计算剩余所学读写的字节数,并再次插入事件循环直至读写完毕。

可以发现其就是把传统 Unix 编程里,非阻塞文件读写的 while 循环换成了 asyncio 的事件循环。

下面是这一过程的示意代码。

def read_step(self, future, n, total):
  res = self.fd.read(n)
  if res is None:
    self.loop.call_soon(self.read_step, future, n, total)
    return
  if not res: # EOF
    future.set_result(bytes(self.rbuffer))
    return
  self.rbuffer.extend(res)
  self.loop.call_soon(self.read_step, future, self.BLOCK_SIZE, total)

def read(self, n=-1):
  future = asyncio.Future(loop=self.loop)

  self.rbuffer.clear()
  self.loop.call_soon(self.read_step, future, min(self.BLOCK_SIZE, n), n)

  return future
Python 相关文章推荐
python中的列表推导浅析
Apr 26 Python
Python中title()方法的使用简介
May 20 Python
Python实现矩阵转置的方法分析
Nov 24 Python
Python实现XML文件解析的示例代码
Feb 05 Python
python实现维吉尼亚加密法
Mar 20 Python
Python3内置模块之json编解码方法小结【推荐】
Dec 09 Python
对python tkinter窗口弹出置顶的方法详解
Jun 14 Python
Python Tkinter 简单登录界面的实现
Jun 14 Python
Python实现的企业粉丝抽奖功能示例
Jul 26 Python
Flask框架学习笔记之使用Flask实现表单开发详解
Aug 12 Python
100行Python代码实现每天不同时间段定时给女友发消息
Sep 27 Python
彻底搞懂 python 中文乱码问题(深入分析)
Feb 28 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
Python随机数random模块使用指南
Sep 09 #Python
You might like
PHP5中新增stdClass 内部保留类
2011/06/13 PHP
解析关于wamp启动是80端口被占用的问题
2013/06/21 PHP
PHP函数extension_loaded()用法实例
2015/01/19 PHP
jQuery TextBox自动完成条
2009/07/22 Javascript
PPK 谈 JavaScript 的 this 关键字 [翻译]
2009/09/29 Javascript
JavaScript中yield实用简洁实现方式
2010/06/12 Javascript
safari,opera嵌入iframe页面cookie读取问题解决方法
2010/06/23 Javascript
jquery 年会抽奖程序
2011/12/22 Javascript
JavaScript实现鼠标滑过处生成气泡的方法
2015/05/16 Javascript
js实现的彩色方块飞舞奇幻效果
2016/01/27 Javascript
js HTML5 Ajax实现文件上传进度条功能
2016/02/13 Javascript
基于javascript实现页面加载loading效果
2020/09/15 Javascript
微信小程序-拍照或选择图片并上传文件
2017/01/06 Javascript
解析Vue2.0双向绑定实现原理
2017/02/23 Javascript
Vue.js子组件向父组件通信的方法实例代码详解
2018/12/10 Javascript
Vue Render函数创建DOM节点代码实例
2020/07/08 Javascript
[03:15]DOTA2-DPC中国联赛1月22日Recap集锦
2021/03/11 DOTA
详解Django框架中用户的登录和退出的实现
2015/07/23 Python
详解Python读取配置文件模块ConfigParser
2017/05/11 Python
python实现生命游戏的示例代码(Game of Life)
2018/01/24 Python
Tornado Web Server框架编写简易Python服务器
2018/07/28 Python
详解Python requests 超时和重试的方法
2018/12/18 Python
python绘制规则网络图形实例
2019/12/09 Python
解决python 虚拟环境删除包无法加载的问题
2020/07/13 Python
基于python的opencv图像处理实现对斑马线的检测示例
2020/11/29 Python
美国流行背包品牌:JanSport(杰斯伯)
2018/03/02 全球购物
Blank NYC官网:夹克、牛仔裤等
2020/12/16 全球购物
高中自我鉴定范文
2013/11/03 职场文书
文秘专业毕业生就业推荐信
2013/11/08 职场文书
咨询公司各岗位职责
2013/12/02 职场文书
副董事长岗位职责
2014/04/02 职场文书
预备党员转正党小组意见
2015/06/01 职场文书
2015年秋季开学典礼校长致辞
2015/07/16 职场文书
浅谈MySQL之select优化方案
2021/08/07 MySQL
Python 全局空间和局部空间
2022/04/06 Python
国际最新研究在陨石中发现DNA主要成分 或由陨石带来地球
2022/04/29 数码科技