【问题标题】:Better to read the whole file, close it, and then loop over it, or loop over while it's open?更好地读取整个文件,关闭它,然后循环它,或者在它打开时循环?
【发布时间】:2019-08-04 07:29:00
【问题描述】:

我想知道,其中哪一种是逐行处理文件内容的更好、更安全的方法。这里的假设是文件的内容非常关键,但文件不是很大,所以内存消耗不是问题。

使用这个尽快关闭文件是否更好:

with open('somefile.txt') as f:
    lines = f.readlines()

for line in lines:
    do_something(line)

或者直接遍历它:

with open('somefile.txt') as f:
    for line in f:
        do_something(line)

这些做法中哪一种通常更好且更被接受?

【问题讨论】:

  • 如果你在谈论一个巨大的文件,第二种方法在内存使用方面可能更有效,因为你没有预先存储整行。
  • @Austin,OP 表示内存不是问题。但是,OP 提到了关键性,想到的第一个问题是回滚/回退。如果出现问题,最好处理文件的全部内容并退出整个文件吗?或者,处理文件的某些内容是否更好,如果确实发生了问题,那么您是回滚已提交的行还是您对已经处理的行没问题,只重播剩余的行?我认为确定文件的重要性(关于如何处理失败事件)将推动您选择循环。
  • 只有在写入文件时,回滚似乎才是问题;对于文件的只读访问,使用文件迭代器或列表迭代器进行迭代并不重要。这只是内存管理的问题。

标签: python python-3.x file file-read


【解决方案1】:

没有“更好”的解决方案。仅仅因为这两者不相等。

第一个将整个文件加载到内存中,然后处理内存中的数据。这具有更快的潜在优势,具体取决于处理的内容。请注意,如果文件大于您拥有的 RAM 量,那么这根本不是一个选项。

第二个仅将文件的一部分加载到内存中,对其进行处理,然后再加载另一部分,依此类推。这通常较慢(尽管您可能看不到差异,因为通常处理时间,尤其是在 Python 中,主导读取时间)但大大减少了内存消耗(假设您的文件超过 1 行)。此外,在某些情况下,它可能更难以使用。例如,假设您正在文件中查找特定模式 xy\nz。现在通过“逐行”加载,您必须记住前一行才能进行正确检查。哪个更难实现(但只有一点)。再说一遍:这取决于你在做什么。

正如您所见,需要权衡取舍,更好的选择取决于您的具体情况。我经常这样做:如果文件相对较小(比如几百兆字节),则将其加载到内存中。

现在您已经提到内容是“关键的”。我不知道这意味着什么,但是例如,如果您尝试对文件进行原子更新或在进程之间读取一致,那么这与您发布的问题是一个非常不同的问题。通常很难,所以我建议使用适当的数据库。 SQLite 是一个简单的选项(同样:取决于您的场景),类似于拥有一个文件。

【讨论】:

  • 文件迭代器本身已经在执行一些缓冲;你不是从字面上一次从磁盘读取一行。
  • @chepner 当然,还有操作系统缓存和磁盘缓存。此外,该文件可能已经在 RAM(即 ram 磁盘)中。但这些都是实现细节。总体思路保持不变:您只从某个地方(无论在哪里)阅读一篇文章。不是一切。
  • 是的,但是它将内存管理的细节留给其他人。相比之下,交错 I/O 和处理的开销几乎不可能显着加快将整个文件读入内存的速度。
  • @chepner 我不会对此争论,因为老实说我还没有测量过速度。我稍微修改了答案,还添加了“难度”作为反对“逐行阅读”的论据。
猜你喜欢
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-14
  • 2018-03-12
  • 2016-11-02
  • 1970-01-01
相关资源
最近更新 更多