如何逐行读取大文件?

601 投票
11 回答
870223 浏览
提问于 2025-04-17 05:38

我想要逐行读取整个文件。有一种方法是先把整个文件读进来,存到一个列表里,然后再逐行处理。这种方法会占用很多内存,所以我在找其他的办法。

我目前的代码是:

for each_line in fileinput.input(input_file):
    do_something(each_line)

    for each_line_again in fileinput.input(input_file):
        do_something(each_line_again)

运行这段代码时出现了一个错误信息:device active

有什么建议吗?

我的目的是计算字符串之间的相似度,也就是说,对于文件中的每一行,我想要计算它与其他每一行的Levenshtein距离。

2022年11月更新:在这个问题提出8个月后,有一个相关的问题得到了很多有用的回答和评论。为了更深入地理解Python的逻辑,也可以看看这个相关的问题 如何在Python中逐行读取文件?

11 个回答

39

去掉换行符:

with open(file_path, 'rU') as f:
    for line_terminated in f:
        line = line_terminated.rstrip('\n')
        ...

使用 通用换行符支持,所有文本文件的行都会被视为以 '\n' 结束,无论文件中的换行符是 '\r''\n' 还是 '\r\n'

编辑 - 如何指定通用换行符支持:

  • 在Unix系统上的Python 2 - open(file_path, mode='rU') - 是必须的 [感谢 @Dave]
  • 在Windows上的Python 2 - open(file_path, mode='rU') - 是可选的
  • Python 3 - open(file_path, newline=None) - 是可选的

newline 参数仅在Python 3中支持,默认值是 None,这表示使用通用换行模式(输入文件可以有任何换行符,输出字符串会变成 \n)。在所有情况下,mode 参数的默认值是 'r'。在Python 3中,U 已被弃用。在Windows上的Python 2中,似乎有其他机制将 \r\n 转换为 \n

文档:

保留原生行结束符:

with open(file_path, 'rb') as f:
    with line_native_terminated in f:
        ...

使用二进制模式仍然可以将文件解析为行,使用 in。每一行会保留文件中的原始换行符。

感谢 @katrielalex回答、Python 的 open() 文档,以及 iPython 的实验。

159

这里有两种节省内存的方法,按效果排序(第一种最好) -

  1. 使用 with - 从 Python 2.5 及以上版本支持
  2. 使用 yield 如果你想更好地控制每次读取多少内容

1. 使用 with

with 是一种很方便且高效的方式来读取大文件。它的优点有:1)在退出 with 代码块后,文件对象会自动关闭。2)可以在 with 块内处理异常。3)内存中的 for 循环可以逐行遍历 f 文件对象。它内部会进行缓冲输入输出(这样可以优化昂贵的输入输出操作)和内存管理。

with open("x.txt") as f:
    for line in f:
        do something with data

2. 使用 yield

有时候你可能想要更精细地控制每次读取多少内容。在这种情况下,可以使用 iteryield。需要注意的是,使用这种方法时,最后需要手动关闭文件。

def readInChunks(fileObj, chunkSize=2048):
    """
    Lazy function to read a file piece by piece.
    Default chunk size: 2kB.

    """
    while True:
        data = fileObj.read(chunkSize)
        if not data:
            break
        yield data

f = open('bigFile')
for chunk in readInChunks(f):
    do_something(chunk)
f.close()

注意事项和补充说明 - 以下方法在读取大文件时效果不如前面提到的两种方法,但了解它们有助于全面理解。

在 Python 中,读取文件行的最常见方法是这样做:

for line in open('myfile','r').readlines():
    do_something(line)

然而,当这样做时,readlines() 函数(read() 函数也是如此)会将整个文件加载到内存中,然后再进行遍历。对于大文件来说,稍微好一点的方法(前面提到的两种方法是最好的)是使用 fileinput 模块,如下所示:

import fileinput

for line in fileinput.input(['myfile']):
    do_something(line)

fileinput.input() 调用会顺序读取行,但在读取后不会将它们保留在内存中,或者说因为 file 在 Python 中是可迭代的,所以这样做也可以。

参考资料

  1. Python with 语句
1378

用Python读取文件的正确方法是这样的:

with open(...) as f:
    for line in f:
        # Do something with 'line'

这里的with语句负责打开和关闭文件,即使在内部代码出错的情况下也能处理好。for line in f把文件对象f当作一个可迭代的对象,这样就能自动使用缓冲输入输出和内存管理,所以你不用担心处理大文件的问题。

应该有一种——最好只有一种——明显的方法来做到这一点。

撰写回答