Python中文件I/O高效操作处理的技巧分享


Posted in Python onFebruary 04, 2017

如何读写文本文件?

实际案例

某文本文件编码格式已直(如UTF-8,GBK,BIG5),在python2.x和python3.x中分别如何读取这些文件?

解决方案

字符串的语义发生了变化:

python2 python3
str bytes
unicode str

python2.x 写入文件前对 unicode 编码,读入文件后对二进制字符串解码

>>> f = open('py2.txt', 'w')
>>> s = u'你好'
>>> f.write(s.encode('gbk'))
>>> f.close()
>>> f = open('py2.txt', 'r')
>>> t = f.read()
>>> print t.decode('gbk')
你好

python3.x 中 open 函数指定 t 的文本模式, encoding 指定编码格式

>>> f = open('py3.txt', 'wt', encoding='utf-8')
>>> f.write('你好')
2
>>> f.close()
>>> f = open('py3.txt', 'rt', encoding='utf-8')
>>> s = f.read()
>>> s
'你好'

如何设置文件的缓冲

实际案例

将文件内容写入到硬盘设备时,使用系统调用,这类I/O操作的时间很长,为了减少I/O操作的次数,文件通常使用缓冲区(有足够多的数据才进行系统调用),文件的缓存行为,分为全缓冲、行缓存、无缓冲。

如何设置Python中文件对象的缓冲行文?

解决方案

全缓冲: open 函数的 buffering 设置为大于1的整数n,n为缓冲区大小

>>> f = open('demo2.txt', 'w', buffering=2048)
>>> f.write('+' * 1024)
>>> f.write('+' * 1023)
# 大于2048的时候就写入文件
>>> f.write('-' * 2)
>>> f.close()

行缓冲: open 函数的 buffering 设置为1

>>> f = open('demo3.txt', 'w', buffering=1)
>>> f.write('abcd')
>>> f.write('1234')
# 只要加上\n就写入文件中
>>> f.write('\n')
>>> f.close()

无缓冲: open 函数的 buffering 设置为0

>>> f = open('demo4.txt', 'w', buffering=0)
>>> f.write('a')
>>> f.write('b')
>>> f.close()

如何将文件映射到内存?

实际案例

  1. 在访问某些二进制文件时,希望能把文件映射到内存中,可以实现随机访问.(framebuffer设备文件)
  2. 某些嵌入式设备,寄存器呗编址到内存地址空间,我们可以映射 /dev/mem 某范围,去访问这些寄存器
  3. 如果多个进程映射到同一个文件,还能实现进程通信的目的

解决方案

使用标准库中的 mmap 模块的 mmap() 函数,它需要一个打开的文件描述符作为参数

创建如下文件

[root@iZ28i253je0Z ~]# dd if=/dev/zero of=demo.bin bs=1024 count=1024
1024+0 records in
1024+0 records out
1048576 bytes (1.0 MB) copied, 0.00380084 s, 276 MB/s
# 以十六进制格式查看文件内容
[root@iZ28i253je0Z ~]# od -x demo.bin 
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
4000000
>>> import mmap
>>> import os
>>> f = open('demo.bin','r+b')
# 获取文件描述符
>>> f.fileno()
3
>>> m = mmap.mmap(f.fileno(),0,access=mmap.ACCESS_WRITE)
>>> type(m)
<type 'mmap.mmap'>
# 可以通过索引获取内容
>>> m[0]
'\x00'
>>> m[10:20]
'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
# 修改内容
>>> m[0] = '\x88'

查看

[root@iZ28i253je0Z ~]# od -x demo.bin 
0000000 0088 0000 0000 0000 0000 0000 0000 0000
0000020 0000 0000 0000 0000 0000 0000 0000 0000
*
4000000

修改切片

>>> m[4:8] = '\xff' * 4

查看

[root@iZ28i253je0Z ~]# od -x demo.bin 
0000000 0088 0000 ffff ffff 0000 0000 0000 0000
0000020 0000 0000 0000 0000 0000 0000 0000 0000
*
4000000
>>> m = mmap.mmap(f.fileno(),mmap.PAGESIZE * 8,access=mmap.ACCESS_WRITE,offset=mmap.PAGESIZE * 4) 
>>> m[:0x1000] = '\xaa' * 0x1000

查看

[root@iZ28i253je0Z ~]# od -x demo.bin 
0000000 0088 0000 ffff ffff 0000 0000 0000 0000
0000020 0000 0000 0000 0000 0000 0000 0000 0000
*
0040000 aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa
*
0050000 0000 0000 0000 0000 0000 0000 0000 0000
*
4000000

如何访问文件的状态?

实际案例

在某些项目中,我们需要获得文件状态,例如:

  • 文件的类型(普通文件、目录、符号链接、设备文件…)
  • 文件的访问权限
  • 文件的最后的访问/修改/节点状态更改时间
  • 普通文件的大小
  • …..

解决方案

当前目录有如下文件

[root@iZ28i253je0Z 2016-09-16]# ll
total 4
drwxr-xr-x 2 root root 4096 Sep 16 11:35 dirs
-rw-r--r-- 1 root root 0 Sep 16 11:35 files
lrwxrwxrwx 1 root root 37 Sep 16 11:36 lockfile -> /tmp/qtsingleapp-aegisG-46d2-lockfile

系统调用

标准库中的os模块下的三个系统调用 stat 、 fstat 、 lstat 获取文件状态

>>> import os
>>> s = os.stat('files')
>>> s
posix.stat_result(st_mode=33188, st_ino=267646, st_dev=51713L, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1473996947, st_mtime=1473996947, st_ctime=1473996947)
>>> s.st_mode
33188
>>> import stat
# stat有很多S_IS..方法来判断文件的类型
>>> stat.S_ISDIR(s.st_mode)
False
# 普通文件
>>> stat.S_ISREG(s.st_mode)
True

获取文件的访问权限,只要大于0就为真

>>> s.st_mode & stat.S_IRUSR
256
>>> s.st_mode & stat.S_IXGRP
0
>>> s.st_mode & stat.S_IXOTH
0

获取文件的修改时间

# 访问时间
>>> s.st_atime
1473996947.3384445
# 修改时间
>>> s.st_mtime
1473996947.3384445
# 状态更新时间
>>> s.st_ctime
1473996947.3384445

将获取到的时间戳进行转换

>>> import time
>>> time.localtime(s.st_atime)
time.struct_time(tm_year=2016, tm_mon=9, tm_mday=16, tm_hour=11, tm_min=35, tm_sec=47, tm_wday=4, tm_yday=260, tm_isdst=0)

获取普通文件的大小

>>> s.st_size
0

快捷函数

标准库中 os.path 下的一些函数,使用起来更加简洁

文件类型判断

>>> os.path.isdir('dirs') 
True
>>> os.path.islink('lockfile')
True
>>> os.path.isfile('files') 
True

文件三个时间

>>> os.path.getatime('files')
1473996947.3384445
>>> os.path.getmtime('files')
1473996947.3384445
>>> os.path.getctime('files')
1473996947.3384445

获取文件大小

>>> os.path.getsize('files') 
0

如何使用临时文件?

实际案例

某项目中,我们从传感器采集数据,每收集到1G数据后,做数据分析,最终只保存分析结果,这样很大的临时数据如果常驻内存,将消耗大量内存资源,我们可以使用临时文件存储这些临时数据(外部存储)

临时文件不用命名,且关闭后会自动被删除

解决方案

使用标准库中的 tempfile 下的 TemporaryFile, NamedTemporaryFile

>>> from tempfile import TemporaryFile, NamedTemporaryFile
# 访问的时候只能通过对象f来进行访问
>>> f = TemporaryFile()
>>> f.write('abcdef' * 100000)
# 访问临时数据
>>> f.seek(0)
>>> f.read(100)
'abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd'
>>> ntf = NamedTemporaryFile()
# 如果要让每次创建NamedTemporaryFile()对象时不删除文件,可以设置NamedTemporaryFile(delete=False)
>>> ntf.name
# 返回当前临时文件在文件系统中的路径
'/tmp/tmppNvBu2'

总结

以上就是关于Python中文件I/O高效处理技巧的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Python 相关文章推荐
python实现中文转换url编码的方法
Jun 14 Python
Python使用sorted排序的方法小结
Jul 28 Python
python实现m3u8格式转换为mp4视频格式
Feb 28 Python
python中验证码连通域分割的方法详解
Jun 04 Python
解决DataFrame排序sort的问题
Jun 07 Python
Python实现操纵控制windows注册表的方法分析
May 24 Python
python aiohttp的使用详解
Jun 20 Python
Python整数与Numpy数据溢出问题解决
Sep 11 Python
python脚本第一行如何写
Aug 30 Python
安装Anaconda3及使用Jupyter的方法
Oct 27 Python
Python3读写ini配置文件的示例
Nov 06 Python
python用海龟绘图写贪吃蛇游戏
Jun 18 Python
Django应用程序中如何发送电子邮件详解
Feb 04 #Python
Python算法应用实战之栈详解
Feb 04 #Python
Python算法应用实战之队列详解
Feb 04 #Python
python模块之re正则表达式详解
Feb 03 #Python
Python用threading实现多线程详解
Feb 03 #Python
win10环境下python3.5安装步骤图文教程
Feb 03 #Python
python strip() 函数和 split() 函数的详解及实例
Feb 03 #Python
You might like
PHP默认安装产生系统漏洞
2006/10/09 PHP
js代码实现微博导航栏
2015/07/30 PHP
Zend Framework教程之Zend_Controller_Plugin插件用法详解
2016/03/07 PHP
Yii2中简单的场景使用介绍
2017/06/02 PHP
详解Yaf框架PHPUnit集成测试方法
2017/12/27 PHP
php实现生成PDF文件的方法示例【基于FPDF类库】
2018/07/21 PHP
JS关闭窗口与JS关闭页面的几种方法小结
2013/12/17 Javascript
文本框文本自动补全效果示例分享
2014/01/19 Javascript
js事件监听机制(事件捕获)总结
2014/08/08 Javascript
JS拖动鼠标画出方框实现鼠标选区的方法
2015/08/05 Javascript
js实现select跳转菜单新窗口效果代码分享(超简单)
2015/08/21 Javascript
javascript生成随机数方法汇总
2015/11/12 Javascript
jQuery的ajax和遍历数组json实例代码
2016/08/01 Javascript
JS取模、取商及取整运算方法示例
2016/10/13 Javascript
JavaScript中关于base64的一些事
2019/05/06 Javascript
Layui 导航默认展开和菜单栏选中高亮设置的方法
2019/09/04 Javascript
vue如何在项目中调用腾讯云的滑动验证码
2020/07/15 Javascript
Python中使用ElementTree解析XML示例
2015/06/02 Python
Python、PyCharm安装及使用方法(Mac版)详解
2017/04/28 Python
Python实现Smtplib发送带有各种附件的邮件实例
2017/06/05 Python
python paramiko模块学习分享
2017/08/23 Python
numpy.linspace 生成等差数组的方法
2018/07/02 Python
Python目录和文件处理总结详解
2019/09/02 Python
Python3显示当前时间、计算时间差及时间加减法示例代码
2019/09/07 Python
Python中输入和输出(打印)数据实例方法
2019/10/13 Python
python+selenium 简易地疫情信息自动打卡签到功能的实现代码
2020/08/22 Python
python 装饰器的实际作用有哪些
2020/09/07 Python
利用css3如何设置没有上下边的列表间隔线
2017/07/03 HTML / CSS
平面设计自荐信
2013/10/07 职场文书
毕业生毕业总结的自我评价范文
2013/11/02 职场文书
对教师的评语
2014/04/28 职场文书
劳模先进事迹材料
2014/12/24 职场文书
毕业实习计划书
2015/01/16 职场文书
教师“一帮一”结对子活动总结
2015/05/07 职场文书
《圆的面积》教学反思
2016/02/19 职场文书
Nginx反向代理至go-fastdfs案例讲解
2021/08/02 Servers