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中的各种函数的使用
May 24 Python
pymssql数据库操作MSSQL2005实例分析
May 25 Python
基于Python实现通过微信搜索功能查看谁把你删除了
Jan 27 Python
windows下安装Python和pip终极图文教程
Mar 05 Python
python机器学习理论与实战(一)K近邻法
Jan 28 Python
python实现音乐下载器
Apr 15 Python
使用Django连接Mysql数据库步骤
Jan 15 Python
解决项目pycharm能运行,在终端却无法运行的问题
Jan 19 Python
Python何时应该使用Lambda函数
Jul 02 Python
Python3.5 win10环境下导入kera/tensorflow报错的解决方法
Dec 19 Python
tensorflow将图片保存为tfrecord和tfrecord的读取方式
Feb 17 Python
Python利用capstone实现反汇编
Apr 06 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
asp和php下textarea提交大量数据发生丢失的解决方法
2008/01/20 PHP
phpMyAdmin 安装配置方法和问题解决
2009/06/08 PHP
php计算年龄精准到年月日
2015/11/17 PHP
Yii视图CGridView实现操作按钮定义地址示例
2016/07/14 PHP
PHP的new static和new self的区别与使用
2019/11/27 PHP
JavaScript与DropDownList 区别分析
2010/01/01 Javascript
JavaScript 通过模式匹配实现重载
2010/08/12 Javascript
关于页面嵌入swf覆盖div层的问题的解决方法
2014/02/11 Javascript
jQuery中append()方法用法实例
2015/01/08 Javascript
JavaScript使用cookie实现记住账号密码功能
2015/04/27 Javascript
JavaScript实现输入框(密码框)出现提示语
2016/01/12 Javascript
js纯数字逐一停止显示效果的实现代码
2016/03/16 Javascript
javascript学习笔记_浅谈基础语法,类型,变量
2016/09/19 Javascript
JS实现用户注册时获取短信验证码和倒计时功能
2016/10/27 Javascript
详解如何在你的Vue项目配置vux
2018/06/04 Javascript
vue2使用keep-alive缓存多层列表页的方法
2018/09/21 Javascript
js实现自动播放匀速轮播图
2020/02/06 Javascript
[39:02]DOTA2亚洲邀请赛 3.31 小组赛 B组 Mineski vs VGJ.T
2018/04/01 DOTA
[38:39]完美世界DOTA2联赛循环赛 IO vs GXR BO2第二场 11.04
2020/11/05 DOTA
使用grappelli为django admin后台添加模板
2014/11/18 Python
python3爬虫之设计签名小程序
2018/06/19 Python
Python datetime和unix时间戳之间相互转换的讲解
2019/04/01 Python
python实现弹窗祝福效果
2019/04/07 Python
使用python实现画AR模型时序图
2019/11/20 Python
基于tensorflow指定GPU运行及GPU资源分配的几种方式小结
2020/02/03 Python
python画图常规设置方式
2020/03/05 Python
美国著名的户外用品品牌:L.L.Bean
2018/01/05 全球购物
我看到了用指针调用函数的不同语法形式
2014/07/16 面试题
自考毕业自我鉴定范文
2013/10/27 职场文书
建筑安全标语
2014/06/07 职场文书
教师求职自荐书
2014/06/14 职场文书
学校欢迎标语
2014/06/18 职场文书
2015年资料员工作总结
2015/04/25 职场文书
公安纪律作风整顿心得体会
2016/01/23 职场文书
该怎么书写道歉信?
2019/07/03 职场文书
Redis缓存-序列化对象存储乱码问题的解决
2021/06/21 Redis