【问题标题】:How to read the n last lines of a file?如何读取文件的最后 n 行?
【发布时间】:2017-03-16 14:02:29
【问题描述】:

我必须读取文件的最后 4 行。

我尝试了以下方法:

top_tb_comp_file = open('../../ver/sim/top_tb_compile.tcl', 'r+')
top_tb_comp_end = top_tb_comp_file.readlines()[:-4]
top_tb_comp_file.close()

没有用(我在top_tb_comp_end 中得到文件的第一行)。

【问题讨论】:

    标签: python python-3.x file


    【解决方案1】:

    以下示例打开一个名为 names.txt 的文件并打印文件中的最后 4 行。应用到您的示例中,您只需去掉第 2、5 和 7 行给出的模式。剩下的很简单。

    #! /usr/bin/env python3
    import collections
    
    
    def main():
        with open('names.txt') as file:
            lines = collections.deque(file, 4)
        print(*lines, sep='')
    
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    • 谢谢你的技巧,但我不确定它是否真的值得。更好的索引在我看来更简单,实际上更快:In [6]: import collections In [7]: liste = list(range(1000000)) In [8]: %timeit lines = collections.deque(liste, 4) 100 loops, best of 3: 8.95 ms per loop In [9]: %timeit lines = liste[-4:] 10000000 loops, best of 3: 115 ns per loop
    • 如果在这两种方法上运行内存配置文件会发生什么?
    • 我不知道该怎么做。请您自己做并分享您的结果吗?
    • 这让我们两个缺乏此类任务的知识。我可以在 Windows 中做一些近似,但大多数人可能更感兴趣的是看到 Linux 的结果。
    • 我刚要离开我的工作地点。我稍后再做并尽快分享
    【解决方案2】:

    您的索引错误。使用[:-4],您所要求的与您实际想要的完全相反。

    尝试以下方法:

    top_tb_comp_file = open('../../ver/sim/top_tb_compile.tcl', 'r+')
    top_tb_comp_end = top_tb_comp_file.readlines()[-4:]
    # you noticed that the '-4' is now before the ':'
    top_tb_comp_file.close()
    

    编辑

    感谢@Noctis,我围绕这个问题做了一些基准测试。关于collection.deque选项和file.readlines选项的速度和内存使用情况。

    @Noctis 建议的 collection 选项在内存使用方面似乎更好 AND 速度:在我的结果中,我观察到临界线 file.readlines()[-4:] 的内存使用有一点峰值这在collections.deque(file, 4) 线上没有发生。此外,我在文件读取阶段重复了速度测试,在这种情况下,collections 选项似乎也更快。

    我在使用 SO 渲染显示此代码的输出时遇到了一些问题,但如果您安装包 memory_profilerpsutil,您应该能够自己看到(带有大文件)。

    import sys
    import collections
    import time
    
    from memory_profiler import profile
    
    
    @profile
    def coll_func(filename):
        with open(filename) as file:
            lines = collections.deque(file, 4)
        return 0
    
    
    @profile
    def indexing_func(filename):
        with open(filename) as file:
            lines = file.readlines()[-4:]
        return 0
    
    
    @profile
    def witness_func(filename):
        with open(filename) as file:
            pass
        return 0
    
    
    def square_star(s_toprint, ext="-"):
        def surround(s, ext="+"):
            return ext + s + ext
    
        hbar = "-" * (len(s_toprint) + 1)
        return (surround(hbar) + "\n"
                + surround(s_toprint, ext='|') + "\n"
                + surround(hbar))
    
    if __name__ == '__main__':
    
        s_fname = sys.argv[1]
        s_func = sys.argv[2]
    
        d_func = {
            "1": coll_func,
            "2": indexing_func,
            "3": witness_func
        }
    
        func = d_func[s_func]
    
        start = time.time()
        func(s_fname)
        elapsed_time = time.time() - start
    
        s_toprint = square_star("Elapsed time:\t{}".format(elapsed_time))
    
        print(s_toprint)
    

    只需输入以下内容:

    python3 -m memory_profiler profile.py "my_file.txt" n
    

    n 为 1、2 或 3。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-28
      • 2015-04-21
      • 1970-01-01
      • 2011-05-06
      • 1970-01-01
      相关资源
      最近更新 更多