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
猜你喜欢
- 用户登录验证脚本,Chkpwd.asp<% '=======用户登录验证脚本======= '如果尚未定义Passed
- Internet Explorer 8 Beta 测试了一年多之后,今天,IE8 终于发布了。它绝对好过 IE7,还有一些不错的新功能,如
- 在Python中我们主要是通过thread和threading这两个模块来实现的,其中Python的threading模块是对thread做
- 前言离过年还有十多天,在这里提前祝各位小伙伴新年快乐呀~先说句题外话:疫情还是比较严峻,各位小伙伴要是出门的话一定要做好防护措施呀,不出门的
- 在pycharm中创建django项目的方法步骤,分享给大家,具体如下:创建完成后,我们可以看看django项目是否可以启动在Termina
- 当用cmd命令行运行python文件时,我们知道可以通过>python pyfile.py来运行python文件,此时的输出会直接打印
- tkinter下载进度条利用python爬取网站数据进行下载时,显示下载进度# 设置下载进度条tk.Label(window, text=&
- 本文实例为大家分享了使用python的twisted框架编写一个简单的聊天室具体代码,供大家参考,具体内容如下下面是基本架构代码:# -*-
- 1、MySQL常用命令create database name; 创建数据库use databasename; 选择数据库drop data
- 本文实例讲述了Python企业编码生成系统之主程序模块。分享给大家供大家参考,具体如下:一 点睛主程序模块包括三部分:1 主程序初始化2 主
- CMake 安装配置 OPENCV 4.1.1 解决各种问题方法一python 可以直接pip install opencv-contrib
- 一、可以使用以下步骤获取两个以逗号分割的字符串的并集:使用explode函数将两个字符串转换为数组,以便可以对其执行操作。使用array_m
- 开始我们将通过示例介绍偶数列表以及在 Python 中创建偶数列表的不同方法。什么是偶数本教程展示了如何在 Python 中制作偶数列表。
- openpyxl特点openpyxl(可读写excel表)专门处理Excel2007及以上版本产生的xlsx文件,xls和xlsx之间转换容
- 比如:Set Connobject=nothing nothing如同英文单词字面意思,没有,没有那个,没有这个,没有东西 Set Conn
- 我们大家都知道CSS功能的强大,而有关CSS基本的排版控制虽然已有详细的使用说明和参考教程,但还有许多丰富的CSS排版能力,是很少能查到的。
- 本文实例讲述了php输出xml必须header的解决方法。分享给大家供大家参考。具体方法如下:问题描述:最近在做一个xml输出时发现我们直接
- 本文实例讲述了CentOS 6/7环境下通过yum安装php7的方法。分享给大家供大家参考,具体如下:安装php7已经是现在linux服务器
- Pyqt5安装并配置到pycharm方法:教你如何用pycharm安装pyqt5及其相关配置一、简介QLabel是界面中的标签类,继承自QF
- 导航标签彼此互斥、完全穷尽。导航标签其实就是一种文字表达形式,我们用标签来代表网站上的各种分类信息。比如“联系我们”这个标签,代表的内容通