【问题标题】:Which way is better to read/write data from/to large files?哪种方式更好地从/向大文件读取/写入数据?
【发布时间】:2016-11-24 09:06:52
【问题描述】:

如果我们需要在处理之前/之后每次从大文件中读取/写入一些数据,那么以下哪种方式(带有一些演示 Python 代码)更好?

  1. 每次需要读/写时打开文件,读/写后立即关闭。这种方式似乎更安全?但是因为我们需要打开和关闭很多次,所以速度较慢? for i in processing_loop: with open(datafile) as f: read_data(...) process_data(...) with open(resultfile,'a') as f: save_data(...) 这看起来很尴尬,但似乎 matlab 在其 .mat 文件 IO 函数 loadsave 中采用了这种方式。我们直接调用loadsave,没有明确的openclose

  2. 打开并关闭文件,直到我们完成所有工作,速度更快,但如果程序出错,文件可能会保持打开状态,或者如果程序终止,文件会损坏不料。 fr = open(datafile) fw = open(resultfile,'a') for i in processing_loop: read_data(...) process_data(...) save_data(...) fr.close() fw.close() 事实上,当程序被杀死时,我有几个 hdf5 文件以这种方式损坏。

似乎人们更喜欢将循环包装在 with 中的第二个。

 with open(...) as f:
     ...

或在异常捕获块中。

我知道这两件事并且我确实使用过它们。但是我的hdf5 文件在程序被杀死时仍然损坏。

  • 有一次我试图将一个巨大的数组写入一个 hdf5 文件并且程序卡住了很长时间,所以我将其杀死,然后文件已损坏。

  • 多次因为服务器突然宕机或运行时间超过挂墙时间而终止程序。

我没有注意损坏是否仅在程序在将数据写入文件时终止时发生。如果是这样,则意味着文件结构已损坏,因为它不完整。因此,我徘徊是否每次都刷新数据会有所帮助,这会增加 IO 负载,但可能会减少终止时将数据写入文件的机会。

我尝试了第一种方法,只有在需要读取/写入数据时才访问文件。但显然速度变慢了。当我们打开/关闭文件句柄时,后台会发生什么?不只是制造/破坏一个指针?为什么open/close 运营成本如此之高?

【问题讨论】:

  • 加载和保存 .mat 文件是完全不同的野兽。它只是从工作区保存变量。 python中的等价物类似于“搁置”。 (事实上​​,scipy 也有 loadmat / savemat 功能)。我会理解这里讨论的读取和写入文件比这更笼统。
  • 我不清楚为什么这些是互斥的?为什么不能将for 循环放在with 块内?您可以使用单个 with 语句打开多个文件。
  • @TasosPapastylianou 是的,我们谈论的是更一般的情况。我只是提到了 mat 文件作为第一种情况的实际示例。 @TheBlackCat 真正的代码可能相当长,并且包含很多嵌套事件,我想很多人无法忍受像我这样丑陋的风格。而with 在意外终止的情况下也无济于事。正如我所提到的,当服务器关闭并且我的程序被杀死时,我的 hdf5 文件以这种方式损坏。

标签: python matlab file io hdf5


【解决方案1】:

如果您担心在“with”语句中使用多个文件,您可以使用复合语句打开多个文件,或嵌套“with”块。这在此处的答案中有详细说明:

How to open a file using the open with statement

至于程序引发错误时会发生什么,这就是 try/except 块的用途。如果您知道预期会出现什么错误,则可以轻松地围绕您的 process_data() 调用。同样,一个 except 块可以捕获多个异常。

https://docs.python.org/3/tutorial/errors.html#handling-exceptions

【讨论】:

  • 嗨@sir_snoopalot,我知道withtry..finally..。但它们并不总是完美无缺。请参阅我的新编辑以获取一些解释。顺便说一句,链接中嵌套的with 对我来说是新的,比嵌套的with 更好
【解决方案2】:

您应该将解决方案 2 中的代码包装在 try except finally 中,并始终在最后关闭文件。这样即使出现错误,您的文件也会自行关闭。

编辑:正如其他人指出的那样,您可以使用 with 为您处理。

【讨论】:

  • 使用with 块自动处理。
  • @TheBlackCat 什么是with 块,我以前没有遇到过这个;这就像java中的“try-with-resources”语句吗? (即本质上是一个 try-catch 块,其中打开的资源会自动关闭?)
  • @TasosPapastylianou with 是特定于 python 的。我不确定Java是否有它。退出块时关闭资源,不管是否有异常。
  • @Lee 是的,所以我想这是同一个概念 (tutorials.jenkov.com/java-exception-handling/…),确保资源正确关闭。除了 java 强制你在 try 块的上下文中使用它,而 with 这似乎是可选的。
  • @TasosPapastylianou:类似,但不完全相同。 while 块与称为“上下文管理器”的东西一起使用,这是一个定义一些特定启动和拆卸方法的类。无论发生什么,这些方法都会被可靠地调用。他们可以打开和关闭文件或其他资源,但不是必须的。在实践中,我看到了三个很大的不同。首先,python 上下文管理器可以看到异常(如果有的话)。其次,设置不必与普通类设置相同。第三,默认情况下不会抑制任何异常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-28
  • 1970-01-01
相关资源
最近更新 更多