2013-05-29 81 views
5

我有一个与配置文件交互的库。当导入库时,初始化代码读取配置文件,可能会更新它,然后将更新的内容写回文件(即使没有更改)。Python何时将文件写入磁盘?

偶尔,我遇到配置文件内容简单消失的问题。具体来说,当我运行多个短文本(使用库)的调用时,会发生这种情况,背靠背数千次。它在同一个目录中从不发生,这导致我相信这是一个有点随机的问题 - 特别是与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将新内容写入文件句柄并关闭它。过程#1:在关闭文件时,Python告诉操作系统将这些内容写入磁盘。
  5. 处理#1闭合并退出
  6. 处理#2被调用
  7. 处理#2将在读出模式的配置文件,但是新的内容尚未同步。进程#2看到一个空文件。
  8. 操作系统最终完成将内容写入磁盘后,进程2读取文件
  9. 进程#2,认为文件为空,设置配置文件的默认值。
  10. 进程#2将其配置文件的版本写入磁盘,覆盖最后一个版本。
+5

不,当Python关闭文件时,文件已被刷新到磁盘。我会说流程#2比您想象的更早打开文件。 –

+2

如果多个进程并发访问一个文件,并且其中至少有一个进程正在写入,则必须同步这些进程以获得一致的结果。这不是特定于Python的东西。 –

+2

即使操作系统没有将数据写入磁盘,只要它被刷出python,就会保证将文件的内容返回到第2个进程,因为访问该文件的任何人都共享了内存缓存。 (除非您在共享文件系统上的不同计算机上运行未配置为一致性的进程,或者存在覆盖文件的竞争条件)。 – nos

回答

1

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

  1. 你描述听起来更可能是一个文件系统错误不是一个Python的bug,以及文件系统错误是件不可思议的事。

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

  3. 是否所有进程都使用相同的文件?在文件上执行“ls -li”以查看其inode号码,并查看它是否发生更改。在你的情况下,它不应该。是否有可能移动文件,移动目录或删除目录并重新创建目录?是否涉及符号链接?

  4. 您确定在程序运行中没有重叠吗?他们中的任何一个是否在最后(即在后台)使用“&”的外壳运行?这很可能意味着第二个在第一个完成之前就开始了。

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

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

+0

这是我所希望的最好的答案,我想。谢谢! – HardlyKnowEm

+0

事实证明,一个实习生编辑了一个库函数来产生另一个Python子流程(使用相同的模块)。在我将这一变化回滚后,问题似乎消失了。这可能也解释了为什么问题只发生在实习生的电脑上。 – HardlyKnowEm

+0

很高兴你知道了! –