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中使用PyHook监听鼠标和键盘事件实例
Jul 18 Python
让python 3支持mysqldb的解决方法
Feb 14 Python
python 调用win32pai 操作cmd的方法
May 28 Python
Python使用filetype精确判断文件类型
Jul 02 Python
Python解决N阶台阶走法问题的方法分析
Dec 28 Python
Python中max函数用于二维列表的实例
Apr 03 Python
Python 如何提高元组的可读性
Aug 26 Python
OpenCV里的imshow()和Matplotlib.pyplot的imshow()的实现
Nov 25 Python
wxpython多线程防假死与线程间传递消息实例详解
Dec 13 Python
python实现猜拳游戏
Mar 04 Python
Python configparser模块常用方法解析
May 22 Python
python 读取.nii格式图像实例
Jul 01 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
动态新闻发布的实现及其技巧
2006/10/09 PHP
php 多个submit提交表单 处理方法
2009/07/07 PHP
php中可能用来加密字符串的函数[base64_encode、urlencode、sha1]
2012/01/16 PHP
php基于curl主动推送最新内容给百度收录的方法
2016/10/14 PHP
关于PHP通用返回值设置方法
2017/03/31 PHP
这段js代码得节约你多少时间
2011/12/20 Javascript
js在指定位置增加节点函数insertBefore()用法实例
2015/01/12 Javascript
JavaScript中的Math.atan2()方法使用详解
2015/06/15 Javascript
Jquery基础教程之DOM操作
2015/08/19 Javascript
jQuery实现的网页右下角tab样式在线客服效果代码
2015/10/23 Javascript
JS组件Form表单验证神器BootstrapValidator
2016/01/26 Javascript
canvas 弹幕效果(实例分享)
2017/01/11 Javascript
JavaScript实现反转字符串的方法详解
2017/04/27 Javascript
Angular 如何使用第三方库的方法
2018/04/18 Javascript
微信小程序中使用ECharts 异步加载数据实现图表功能
2018/07/13 Javascript
vue进入页面时滚动条始终在底部代码实例
2019/03/26 Javascript
详解服务端预渲染之Nuxt(介绍篇)
2019/04/07 Javascript
使用Angular9和TypeScript开发RPG游戏的方法
2020/03/25 Javascript
如何利用 JS 脚本实现网页全自动秒杀抢购功能
2020/10/12 Javascript
原生JS运动实现轮播图
2021/01/02 Javascript
[02:31]《DAC最前线》之选手酒店现场花絮
2015/01/30 DOTA
[42:35]2018DOTA2亚洲邀请赛3月30日 小组赛A组 VG VS OpTic
2018/03/31 DOTA
用Python写一个无界面的2048小游戏
2016/05/24 Python
python2.7 安装pip的方法步骤(管用)
2019/05/05 Python
Django多进程滚动日志问题解决方案
2019/12/17 Python
Python标准库itertools的使用方法
2020/01/17 Python
Python pip install之SSL异常处理操作
2020/09/03 Python
CSS3中的content属性使用示例
2015/07/20 HTML / CSS
司机岗位职责
2013/11/15 职场文书
搞笑征婚广告词
2014/03/17 职场文书
小学运动会演讲稿
2014/08/25 职场文书
政风行风建设整改方案
2014/10/27 职场文书
总经理司机岗位职责
2015/04/10 职场文书
社区环境卫生倡议书
2015/04/29 职场文书
公司年会主持词范文!
2019/05/07 职场文书
Nginx已编译的nginx-添加新模块
2021/04/01 Servers