Python文本处理之按行处理大文件的方法
作者:aturbofly 发布时间:2023-01-24 11:11:34
以行的形式读出一个文件最简单的方式是使用文件对象的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”
来源:https://blog.csdn.net/Allenalex/article/details/54891180


猜你喜欢
- 这篇博客讲的是SQL server的分页方法,用的SQL server 2012版本。下面都用pageIndex表示页数,pageSize表
- 在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流!为了保证在业务高峰期,线上系统也能保证一定的弹性和稳定性,最有效的方案就是进行服
- 这篇文章主要介绍了python 哈希表实现简单python字典代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学
- 本文实例讲述了python清除字符串里非字母字符的方法。分享给大家供大家参考。具体如下:s = "hello world! how
- 本文实例讲述了GO语言标准错误处理机制error用法。分享给大家供大家参考。具体分析如下:在 Golang 中,错误处理机制一般是函数返回时
- Microsoft SQL Server 2005 Mobile Edition 3.0 (SQL Server Mobile) 支持两种与
- 首先,在数据库中创建一个表,用于存放图片:CREATE TABLE Images(Id INT PRIMARY KEY AUTO_INCRE
- 本文实例为大家分享了JavaScript实现网页计算器的具体代码,供大家参考,具体内容如下要求:在网页上实现简单的计算器功能和界面CSS样式
- 前因后果公司有人阳了,今天在家上班,突然小姨子就问我有没有baidu文库会员,想下载点东西,我心想这还要会员?用Python不是分分钟的事情
- element-ui中el-form自定义验证需求在输入项目名称后,调用后端接口isNameOnly,若已存在,则效果如下图:1.先设置校验
- 看网络小说一般会攒上一波,然后导入Kindle里面去看,但是攒的多了,机械的Ctrl+C和Ctrl+V实在是OUT,所以就出现了此文。其实P
- 1、#coding:utf-8chose = [ ('foo',1,2), ('bar
- 如下所示:import pandas as pd #显示所有列pd.set_option('display.max_columns&
- 需要处理原始的音频,所以给服务器的环境安装librosa的包pip install librosa直接pip install librosa
- Python是一门高级编程语言,而且Python语言适合零基础人员学习,也是初学者的首选。如何学习好Python:1. 要有决心做任何事情,
- 通过企业管理器设置数据库的定期自动备份计划。 1、打开企业管理器,双击打开你的服务器 2、然后点上面菜单中的工具-->选择数据库维护计
- 今天小编就为大家分享一篇使用pandas把某一列的字符值转换为数字的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧使用
- @property作用:python的@property是python的一种装饰器,是用来修饰方法的。我们可以使用@property装饰器来
- ♩ 背景昨天在自己的 Laravel5.5 框架项目中,希望集成 Layer 的图片上传功能 但是在 ajax(POST) 提交请求时,一直
- 列表对象pop()方法的使用pop() 方法用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。语法:verse.pop(in