Python文本处理之按行处理大文件的方法


Posted in Python onApril 09, 2018

以行的形式读出一个文件最简单的方式是使用文件对象的readline()、readlines()和xreadlines()方法。

Python2.2+为这种频繁的操作提供了一个简化的语法——让文件对象自身在行上高效迭代(这种迭代是严格的向前的)。

为了读取整个文件,可能要使用read()方法,且使用字符串的split()来将它拆分WEIGHT行或其他块。

下面是一些例子:

>>> for line in open('chap1.txt'): # Python 2.2+
  ...  # process each line in some manner
  ...  pass
  ...
  >>> linelist = open('chap1.txt').readlines()
  >>> print linelist[1849],
  EXERCISE: Working with lines from a large file
  >>> txt = open('chap1.txt').read()
  >>> from os import linesep
  >>> linelist2 = txt.split(linesep)

如果文件不大,读取整个文件内容也没有关系。但如果是大文件,时间和内存就是要重点关注的了。比如,复杂文档或者活动日志文件,通常有上M,甚至很多G的大小。就算这些文件的内容没有超出可用内存的尺寸,读取他们仍然是相当耗时的。

很明显,如果你需要处理文件的每一行,那就必须读取整个文件;如果可以按序列处理,xreadlines方法是一种更节约内存的方法。但是对于那些仅仅需要一个大文件的一部分行的应用,要获得提高其实并不难。对于这一点,模块“linecache”非常合适。

具有缓存功能的行列表

使用linecache可以直接从一个文件中读取指定行:

>>> import linecache
  >>> print linecache.getline('chap1.txt',1850),
  PROBLEM: Working with lines from a large file

记住,linecache.getline()的计数是从1开始的。

如果有一个即具有“linecache”的效率,又有列表的一些功能的对象就好了。这个对象不仅可以枚举和索引,同时还支持切片。

#------------------ cachedlinelist.py --------------------#
  import linecache, types
  class CachedLineList:
   # Note: in Python 2.2+, it is probably worth including:
   # __slots__ = ('_fname')
   # ...and inheriting from 'object'
   def __init__(self, fname):
    self._fname = fname
   def __getitem__(self, x):
    if type(x) is types.SliceType:
     return [linecache.getline(self._fname, n+1)
       for n in range(x.start, x.stop, x.step)]
    else:
     return linecache.getline(self._fname, x+1)
   def __getslice__(self, beg, end):
    # pass to __getitem__ which does extended slices also
    return self[beg:end:1]

使用这个新对象几乎和使用一个由“open(fname).readlines()”创建的列表一样。除了它的效率要更高之外(特别是在内存使用方面):

>>> from cachedlinelist import CachedLineList
  >>> cll = CachedLineList('../chap1.txt')
  >>> cll[1849]
  ' PROBLEM: Working with lines from a large file\r\n'
  >>> for line in cll[1849:1851]: print line,
  ...
  PROBLEM: Working with lines from a large file
  ----------------------------------------------------------
  >>> for line in cll[1853:1857:2]: print line,
  ...
  a matter of using the '.readline()', '.readlines()' and
  simplified syntax for this frequent operation by letting the

随机行

有时候,特别是为了测试,可能需要检查某些典型的行。人们很容易就误认为一个对文本的前面几行和后面几行有效的处理就能适用任何其他地方。很不幸,很多文件的前几行和最后几行通常都是非典型的:有时候是消息头或注脚,有时候可能是开发时的日志文件的前几行等等。穷举测试整个文件并不是你想要的,通常这样也非常的耗时。

在大多数系统上,查找一个文件中的特定位置要比读出该位置前的所有内容直到到达该位置快的多。

就算使用linecache,要到达缓存行,你也需要一个字节一个字节的读取前面的内容。从一个大文件中找随机行的最快的方式是,先找到一个随机位置,然后读取该位置相对前后的少数字节。

#-------------------- randline.py ------------------------#
  #!/usr/bin/python
  """Iterate over random lines in a file (req Python 2.2+)
  From command-line use: % randline.py <fname> <numlines>
  """
  import sys
  from os import stat, linesep
  from stat import ST_SIZE
  from random import randrange
  MAX_LINE_LEN = 4096
  #-- Iterable class
  class randline(object):
   __slots__ = ('_fp','_size','_limit')
   def __init__(self, fname, limit=sys.maxint):
    self._size = stat(fname)[ST_SIZE]
    self._fp = open(fname,'rb')
    self._limit = limit
   def __iter__(self):
    return self
   def next(self):
    if self._limit <= 0:
     raise StopIteration
    self._limit -= 1
    pos = randrange(self._size)
    priorlen = min(pos, MAX_LINE_LEN) # maybe near start
    self._fp.seek(pos-priorlen)
    # Add extra linesep at beg/end in case pos at beg/end
    prior = linesep + self._fp.read(priorlen)
    post = self._fp.read(MAX_LINE_LEN) + linesep
    begln = prior.rfind(linesep) + len(linesep)
    endln = post.find(linesep)
    return prior[begln:]+post[:endln]
  #-- Use as command-line tool
  if __name__=='__main__':
   fname, numlines = sys.argv[1], int(sys.argv[2])
   for line in randline(fname, numlines):
    print line

关于上面的实现,需要注意以下细节:

(1)在行迭代中,相同的行可能会被多次选中。当然,如果你只是从大文件中选很少行的话,这种情况通常不会出现。

(2)既然是选中包含随机位置的行,那就意味着更 有可能选择长的行(译注:这是为什么?没有明白)。

本文翻译自Text Processing in Python

中“PROBLEM: Working with lines from a large file”

以上这篇Python文本处理之按行处理大文件的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python正则表达式抓取成语网站
Nov 20 Python
python三元运算符实现方法
Dec 17 Python
仅用50行代码实现一个Python编写的计算器的教程
Apr 17 Python
解决Python3.5+OpenCV3.2读取图像的问题
Dec 05 Python
Python查找数组中数值和下标相等的元素示例【二分查找】
Feb 13 Python
Python爬虫使用浏览器cookies:browsercookie过程解析
Oct 22 Python
wxPython实现画图板
Aug 27 Python
python cv2读取rtsp实时码流按时生成连续视频文件方式
Dec 25 Python
如何基于python3和Vue实现AES数据加密
Mar 27 Python
Python unittest生成测试报告过程解析
Sep 08 Python
浅析Python打包时包含静态文件处理方法
Jan 15 Python
Python开发.exe小工具的详细步骤
Jan 27 Python
Python网络编程使用select实现socket全双工异步通信功能示例
Apr 09 #Python
Python网络编程之TCP套接字简单用法示例
Apr 09 #Python
python3 读写文件换行符的方法
Apr 09 #Python
Python基于TCP实现会聊天的小机器人功能示例
Apr 09 #Python
Python生成任意范围任意精度的随机数方法
Apr 09 #Python
python网络爬虫学习笔记(1)
Apr 09 #Python
Python中defaultdict与lambda表达式用法实例小结
Apr 09 #Python
You might like
PHP+Ajax实时自动检测是否联网的方法
2015/07/01 PHP
再谈PHP中单双引号的区别详解
2016/06/12 PHP
php layui实现前端多图上传实例
2019/07/30 PHP
js常用代码段整理
2011/11/30 Javascript
jquery仿QQ商城带左右按钮控制焦点图片切换滚动效果
2013/06/27 Javascript
JS页面延迟执行一些方法(整理)
2013/11/11 Javascript
jQuery实现右键菜单、遮罩等效果代码
2016/09/27 Javascript
JS获取填报扩展单元格控件的值的解决办法
2017/07/14 Javascript
es7学习教程之Decorators(修饰器)详解
2017/07/21 Javascript
动态创建Angular组件实现popup弹窗功能
2017/09/15 Javascript
vue中各选项及钩子函数执行顺序详解
2018/08/25 Javascript
JS实现悬浮球只在一侧滑动并且是横屏状态下
2020/08/19 Javascript
uniapp实现可以左右滑动导航栏
2020/10/21 Javascript
[01:50]2014DOTA2西雅图邀请赛 专访欢乐周宝龙
2014/07/08 DOTA
[41:21]夜魇凡尔赛茶话会 第三期02:看图识人
2021/03/11 DOTA
调试Python程序代码的几种方法总结
2015/04/28 Python
python 2.7.13 安装配置方法图文教程
2018/09/18 Python
Python从Excel中读取日期一列的方法
2018/11/28 Python
对pycharm 修改程序运行所需内存详解
2018/12/03 Python
运行tensorflow python程序,限制对GPU和CPU的占用操作
2020/02/06 Python
安装不同版本的tensorflow与models方法实现
2021/02/20 Python
CSS3弹性盒模型开发笔记(二)
2016/04/26 HTML / CSS
html5 拖拽上传图片实例演示
2013/04/01 HTML / CSS
保加利亚服装和鞋类购物网站:Bibloo.bg
2020/11/08 全球购物
JS原生实现轮播图的几种方法
2021/03/23 Javascript
婚礼证婚人证婚词
2014/01/13 职场文书
研发工程师岗位职责
2014/04/28 职场文书
无子女夫妻离婚协议书(4篇)
2014/10/20 职场文书
预备党员群众路线思想汇报2014
2014/10/25 职场文书
铣工实训报告
2014/11/05 职场文书
给老婆的保证书
2015/01/16 职场文书
学生会个人总结范文
2015/02/15 职场文书
2016年学校“3.12”植树节活动总结
2016/03/16 职场文书
2019最新校园运动会广播稿!
2019/06/28 职场文书
jquery插件实现代码雨特效
2021/04/24 jQuery
Python写情书? 10行代码展示如何把情书写在她的照片里
2022/04/21 Python