【发布时间】: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 以读取模式打开配置文件,完成后将其关闭。
- 进程#1 以写入模式打开配置文件,擦除其所有内容。内容的擦除将同步到磁盘。
- 进程 #1 将新内容写入文件句柄并关闭它。
- 过程 #1:关闭文件后,Python 告诉操作系统将这些内容写入磁盘。
- 进程 #1 关闭并退出
- 进程 #2 被调用
- 进程 #2 以读取模式打开配置文件,但尚未同步新内容。进程 #2 看到一个空文件。
- 在进程 2 读取文件后,操作系统终于完成了将内容写入磁盘
- 进程 #2,认为文件为空,为配置文件设置默认值。
- 进程 #2 将其配置文件版本写入磁盘,覆盖上一个版本。
【问题讨论】:
-
不,当 Python 关闭文件时,文件已被刷新到磁盘。我会说进程 #2 比您想象的更早地打开文件。
-
如果多个进程同时访问一个文件并且其中至少有一个写入文件,您必须同步这些进程以获得一致的结果。这不是 Python 特有的。
-
即使操作系统不将数据写入磁盘,它也保证将文件内容返回给2.进程,只要它被刷新出python,因为有内存缓存由访问该文件的任何人共享。 (除非您在未配置一致性的共享文件系统上的不同机器上运行进程,或者在覆盖文件时存在竞争条件。)
-
一种可能的问题是:一旦您使用
'w'打开,内容就会被截断。如果另一个进程在再次写入之前从它读取,它将为空。 -
@misfavor 向进程 1 添加一些调试,检查它生成的文件永远不会为空,关联进程 1 和 2 之间的文件名,以便您知道哪个运行产生了错误文件
标签: python file unix file-io operating-system