【问题标题】:When does Python write a file to disk?Python 什么时候将文件写入磁盘?
【发布时间】:2013-05-25 06:11:04
【问题描述】:

我有一个与配置文件交互的库。导入库时,初始化代码会读取配置文件,可能会对其进行更新,然后将更新后的内容写回文件中(即使没有任何更改)。

我偶尔会遇到配置文件内容消失的问题。具体来说,当我连续数千次运行短脚本(使用库)多次调用时,就会发生这种情况。它从不在同一个目录中发生,这让我相信这是一个有点随机的问题——特别是 IO 的竞争条件。

调试起来很痛苦,因为我永远无法可靠地重现该问题,而且它只发生在某些系统上。我怀疑可能会发生什么,但我想看看我在 Python 中的文件 I/O 图片是否正确。

所以问题是,Python 程序什么时候真正将文件内容写入磁盘?我认为内容会在文件关闭时写入磁盘,但我可以'不解释这个错误。当 python 关闭一个文件时,它会将内容刷新到磁盘本身,还是简单地将其排队到文件系统? 是否可以在 Python 终止后将文件内容写入磁盘? 我可以通过使用fp.flush(); os.fsync(fp.fileno())(其中fp 是文件句柄)来避免这个问题吗?

如果重要的话,我正在 Unix 系统(特别是 Mac OS X)上编程。 编辑:另外,请记住这些进程不是同时运行的。

附录:这是我怀疑的特定竞争条件:

  1. 进程 #1 被调用。
  2. 进程 #1 以读取模式打开配置文件,完成后将其关闭。
  3. 进程#1 以写入模式打开配置文件,擦除其所有内容。内容的擦除将同步到磁盘。
  4. 进程 #1 将新内容写入文件句柄并关闭它。
  5. 过程 #1:关闭文件后,Python 告诉操作系统将这些内容写入磁盘。
  6. 进程 #1 关闭并退出
  7. 进程 #2 被调用
  8. 进程 #2 以读取模式打开配置文件,但尚未同步新内容。进程 #2 看到一个空文件。
  9. 在进程 2 读取文件后,操作系统终于完成了将内容写入磁盘
  10. 进程 #2,认为文件为空,为配置文件设置默认值。
  11. 进程 #2 将其配置文件版本写入磁盘,覆盖上一个版本。

【问题讨论】:

  • 不,当 Python 关闭文件时,文件已被刷新到磁盘。我会说进程 #2 比您想象的更早地打开文件。
  • 如果多个进程同时访问一个文件并且其中至少有一个写入文件,您必须同步这些进程以获得一致的结果。这不是 Python 特有的。
  • 即使操作系统不将数据写入磁盘,它也保证将文件内容返回给2.进程,只要它被刷新出python,因为有内存缓存由访问该文件的任何人共享。 (除非您在未配置一致性的共享文件系统上的不同机器上运行进程,或者在覆盖文件时存在竞争条件。)
  • 一种可能的问题是:一旦您使用'w' 打开,内容就会被截断。如果另一个进程在再次写入之前从它读取,它将为空。
  • @misfavor 向进程 1 添加一些调试,检查它生成的文件永远不会为空,关联进程 1 和 2 之间的文件名,以便您知道哪个运行产生了错误文件

标签: python file unix file-io operating-system


【解决方案1】:

这几乎肯定不是 python 的错。如果 python 关闭文件,或者干净地退出(而不是被信号杀死),那么操作系统将拥有文件的新内容。任何后续打开都应返回新内容。一定有更复杂的事情发生。以下是一些想法。

  1. 您所描述的听起来更有可能是文件系统错误而不是 Python 错误,而且文件系统错误也不太可能。

  2. 如果您的文件实际上驻留在远程文件系统中,则文件系统错误的可能性要大得多。是吗?

  3. 所有进程都使用同一个文件吗?对文件执行“ls -li”以查看其 inode 编号,并查看它是否会更改。在您的情况下,它不应该。是否有可能正在移动文件、移动目录或删除目录并重新创建它们?是否涉及符号链接?

  4. 您确定在您的程序运行过程中没有重叠吗?它们中的任何一个是否从末尾带有“&”的外壳运行(即在后台)?这很容易意味着在第一个完成之前就开始了第二个。

  5. 是否有其他程序写入同一文件?

  6. 这不是您的问题,但如果您需要原子更改(以便任何并行运行的程序只能看到旧版本或新版本,而不是空文件),实现它的方法是将新内容写入另一个文件(例如“foo.tmp”),然后执行 os.rename("foo.tmp", "foo")。重命名是原子的。

【讨论】:

  • 我想这是我希望得到的最佳答案。谢谢!
  • 事实证明,一名实习生编辑了一个库函数以生成另一个 Python 子进程(使用相同的模块)。在我回滚该更改后,问题似乎消失了。这可能也解释了为什么问题只发生在实习生的电脑上。
猜你喜欢
  • 1970-01-01
  • 2016-01-12
  • 2013-03-05
  • 2012-11-01
  • 2020-12-21
  • 1970-01-01
  • 2019-07-26
  • 1970-01-01
相关资源
最近更新 更多