【问题标题】:When should I ever use file.read() or file.readlines()?我什么时候应该使用 file.read() 或 file.readlines()?
【发布时间】:2016-11-01 12:14:54
【问题描述】:

我注意到,如果我对打开的文件进行迭代,在不“读取”的情况下迭代它会快得多。

l = open('file','r')
for line in l:
    pass (or code)

快很多
l = open('file','r')
for line in l.read() / l.readlines():
    pass (or code)

第二个循环将花费大约 1.5 倍的时间(我在完全相同的文件上使用 timeit,结果是 0.442 对 0.660),并且会给出相同的结果。

那么 - 我什么时候应该使用 .read() 或 .readlines()?

因为我总是需要遍历我正在阅读的文件,并且在艰难地学习了 .read() 在大数据上的速度有多慢之后——我似乎无法想象再次使用它。

【问题讨论】:

  • 请澄清。 timeitread 还是 readlines 的测量值?我希望read 循环需要更长的时间,因为它返回一个字符串,所以迭代它会逐个字符地进行。如果您的文件平均每行有 100 个字符,那么 for line in l.read() 循环中的代码将执行 100 倍于 for line in l: 循环中的代码。
  • 它也适用于 readlines()。令人惊讶的是 read() 或 readlines() 之间几乎没有时间差......

标签: python io timeit


【解决方案1】:
#The difference between file.read(), file.readline(), file.readlines()
file = open('samplefile', 'r')
single_string = file.read()    #Reads all the elements of the file 
                               #into a single string(\n characters might be included)
line = file.readline()         #Reads the current line where the cursor as a string 
                               #is positioned and moves to the next line
list_strings = file.readlines()#Makes a list of strings

【讨论】:

    【解决方案2】:

    readlines()for line in file 更好,因为您知道您感兴趣的数据从例如第 2 行开始。你可以直接写readlines()[1:]

    这样的用例是当您有一个制表符/逗号分隔值文件并且第一行是标题(并且您不想为 tsv 或 csv 文件使用其他模块)时。

    【讨论】:

    • 我认为您将 readline() 与 readlines() 混淆了?也很确定这个对象在 Python-3 之后是不可索引的
    • @JonathanSimon 你是对的,我改了readline -> readlines
    【解决方案3】:

    对您的问题的简短回答是,这三种读取文件位的方法中的每一种都有不同的用例。如上所述,f.read() 将文件作为单独的字符串读取,因此允许相对简单的文件范围操作,例如文件范围的正则表达式搜索或替换。

    f.readline() 读取文件的单行,允许用户解析单行而不必读取整个文件。使用f.readline() 还允许在读取文件时应用逻辑比完整的逐行迭代更容易,例如当文件中途更改格式时。

    使用语法for line in f: 允许用户逐行遍历文件,如问题中所述。

    (如另一个答案中所述,此文档非常好读):

    https://docs.python.org/3/tutorial/inputoutput.html#methods-of-file-objects

    注意: 之前有人声称f.readline() 可用于在 for 循环迭代期间跳过一行。但是,这在 Python 2.7 中不起作用,并且可能是一个有问题的做法,因此此声明已被删除。

    【讨论】:

    • 在文件上混合readlinefor 循环实际上不起作用; readline 不理解 next 实现的缓冲。如果你想跳过for循环中的一行,你应该在文件上调用next
    • 我刚刚用 python 3.4 测试过。 readline() 似乎将循环缓冲区向前移动。让我快速检查一下 python 2
    • 啊,你是对的 python 2.7。我会编辑我的答案。谢谢,很高兴知道!
    • 你能举一个实际使用 read() 的例子吗?我唯一能想到的是,如果您将密码存储在文件中并且您想读取它 - 那么使用 .read() 会比文件代码中的 for l 快一点。但是对于任何正常大小的文件...?
    • 已添加。该示例是否有助于澄清您的问题?如果需要,我可以举一个更有根据的例子。
    【解决方案4】:

    请注意,readline() 无法与在 for 循环中读取所有行的情况相提并论,因为它逐行读取,并且存在其他人已经指出的开销。

    我在两个相同的片段上运行timeit,但一个带有for循环,另一个带有readlines()。你可以在下面看到我的 sn-p:

      
    def test_read_file_1():  
        f = open('ml/README.md', 'r')  
        for line in f.readlines():  
            print(line)  
      
      
    def test_read_file_2():  
        f = open('ml/README.md', 'r')  
        for line in f:  
            print(line)  
      
      
    def test_time_read_file():  
        from timeit import timeit  
      
        duration_1 = timeit(lambda: test_read_file_1(), number=1000000)  
        duration_2 = timeit(lambda: test_read_file_2(), number=1000000)  
      
        print('duration using readlines():', duration_1)  
        print('duration using for-loop:', duration_2)
    

    结果:

    duration using readlines(): 78.826229238
    duration using for-loop: 69.487692794
    

    我想说的是,for-loop 更快,但如果两者都有可能,我宁愿readlines()

    【讨论】:

      【解决方案5】:

      Eessketit

      这是一个绝妙的答案。 / 好消息是,每当您使用 readline() 函数时,它都会读取一行......然后它就无法再次读取它了。您可以使用seek()函数返回该位置。要返回零位,只需输入f.seek(0)

      同样,f.tell() 函数会让你知道你在哪个位置。

      【讨论】:

        【解决方案6】:

        希望这会有所帮助!

        https://docs.python.org/2/tutorial/inputoutput.html#methods-of-file-objects

        当 size 省略或为负时,将读取并返回文件的全部内容;如果文件是你机器内存的两倍,那是你的问题

        抱歉所有的修改!

        为了从文件中读取行,你可以遍历文件对象。这是内存效率高、速度快且代码简单:

        for line in f:
            print line,
        
        This is the first line of the file.
        Second line of the file
        

        【讨论】:

        • 这不是对 C 或 Python API 的准确描述。
        • 我想我不会很好地解释它,这就是我直接从文档中提取其余答案的原因。
        • C 不默认逐行读取文件。在 C 中甚至没有一个标准的函数来逐行读取文件。 getline 是 POSIX 扩展。此外,f.read() 上的循环不会在每次迭代时读取整个文件,也不会遍历行。
        • 我指的不是getline,而是fscanf。
        • 去年我考CS108的时候也是这样,不知道什么时候变了,但我一定会调查一下。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-09-07
        • 1970-01-01
        • 2021-06-13
        • 2012-09-22
        • 1970-01-01
        • 2012-12-23
        • 2021-07-13
        相关资源
        最近更新 更多