为什么Python中readline()比readlines()慢得多?

12 投票
2 回答
20533 浏览
提问于 2025-04-18 01:53

在一次面试中,面试官问我为什么在Python中,readline()readlines()慢得多?

我回答说,readlines()需要多次读取,这样就需要更多的开销。

我不知道我的回答是否正确。

如果我的回答是正确的,那这个开销指的是什么呢?

谢谢!

附注:我知道readline()readlines()之间的区别!!!

readlines()一次性读取整个文件,而readline()只能读取一行。

我希望有人能告诉我一些关于从磁盘读取文件的输入输出知识。

2 个回答

-1

根据文档,关于file.readline()

f.readline()这个方法是从文件中读取一行内容;在字符串的末尾会保留一个换行符(\n),只有在文件的最后一行如果没有换行符时,这个换行符才会被省略。

它会从文件中读取一整行。字符串的末尾会保留换行符(但如果文件的最后一行不完整,可能就没有这个换行符)。如果你给它一个大小参数,并且这个参数是非负的,它会限制读取的字节数(包括末尾的换行符),这时可能会返回一行不完整的内容。当大小参数不为0时,只有在立刻遇到文件结束(EOF)时,才会返回一个空字符串。

还有关于readlines()

如果你想把文件的所有行都读到一个列表里,可以使用list(f)或者f.readlines()。

这个方法会一直读取直到文件结束(EOF),并返回一个包含读取到的行的列表。如果你提供了一个可选的大小提示参数,方法就不会一直读取到文件结束,而是会读取大约sizehint字节的完整行(可能会向上调整到内部缓冲区的大小)。实现了类似文件接口的对象可能会选择忽略这个大小提示,如果它无法实现,或者实现起来效率不高。

所以,readlines实际上是利用readline这个方法“多次读取”文件。其他回答可以更详细地解释这两者的性能差异。

24

为了好玩,我写了一些函数,用来逐行读取一个文件,并把每一行放到一个列表里:

#!/usr/bin/python

def readlines():
    with open("sorted_output.txt") as f:
        line = f.readlines()

def readline():
    with open("sorted_output.txt") as f:
        line = f.readline()
        lines = []
        while line:
            lines.append(line)
            line = f.readline()

def iterate():
    with open("sorted_output.txt") as f:
        lines = []
        for line in f:
            lines.append(line)

def comprehension():
    with open("sorted_output.txt") as f:
        lines = [line for line in f]

下面是这些函数在处理一个有69,073行的文件时的表现,使用的是Python 2.6(注意,这些结果在更新版本的Python中可能会有所不同):

dano@hostname:~> python -mtimeit -s 'import test' 'test.readline()'
10 loops, best of 3: 78.3 msec per loop
dano@hostname:~> python -mtimeit -s 'import test' 'test.readlines()'
10 loops, best of 3: 21.6 msec per loop
dano@hostname:~> python -mtimeit -s 'import test' 'test.comprehension()'
10 loops, best of 3: 23.6 msec per loop
dano@hostname:~> python -mtimeit -s 'import test' 'test.iterate()'
10 loops, best of 3: 33.3 msec per loop

从结果来看,readlines()是最快的,虽然用列表推导式逐行读取的速度几乎和它一样快。我猜测不同方法之间的速度差异主要是因为Python中函数调用的开销很大(调用的函数越多,速度就越慢),但可能还有其他因素。希望比我更懂的人能对此做一些解释。

除了性能,选择使用哪种方法时,另一个重要的考虑是内存消耗。使用readlines()会一次性把整个文件读入内存。如果你处理的是一个非常大的文件,这可能会导致严重的性能问题,甚至可能让程序崩溃,因为你试图一次性把整个文件读入内存。在这种情况下,你应该使用iterate()的方法,因为它一次只读取一行到内存中。如果你只是对每一行进行一些处理然后就丢掉,这种方法通常是更好的选择,尽管它的速度可能比readlines()稍慢,因为这样不会占用太多内存。当然,如果你最终的目标是把整个文件存储在一个Python列表中,那你无论如何都得承担这个内存消耗,所以readlines()也没问题。

撰写回答