Python的file.flush()到底在做什么?


137

我在Python 文档的File Objects中找到了这个:

flush()不一定会将文件的数据写入磁盘。使用flush()和os.fsync()来确保此行为。

所以我的问题是:Python到底在flush做什么?我以为这会强制将数据写入磁盘,但现在我发现并没有。为什么?

Answers:


219

通常涉及两个级别的缓冲:

  1. 内部缓冲器
  2. 操作系统缓冲区

内部缓冲区是由您针对其进行编程的运行时/库/语言创建的缓冲区,其目的是通过避免每次写入都调用系统来加快处理速度。取而代之的是,当您写入文件对象时,您将写入其缓冲区,并且只要缓冲区被填满,就会使用系统调用将数据写入实际文件。

但是,由于操作系统缓冲区的原因,这可能并不意味着数据已写入disk。这可能仅意味着将数据从运行时维护的缓冲区复制到操作系统维护的缓冲区。

如果您写了一些东西,并且它最终在缓冲区中(仅),并且切断了计算机的电源,则当计算机关闭时,该数据将不在磁盘上。

因此,为了帮助您在各自的对象上使用flushfsync方法。

第一个flush会简单地将程序缓冲区中残留的所有数据写到实际文件中。通常,这意味着数据将从程序缓冲区复制到操作系统缓冲区。

具体来说,这意味着如果另一个进程打开了要读取的相同文件,它将能够访问刚刷新到该文件的数据。但是,这不一定意味着它已“永久”存储在磁盘上。

为此,您需要调用os.fsync确保所有操作系统缓冲区与它们所使用的存储设备同步的方法,换句话说,该方法会将数据从操作系统缓冲区复制到磁盘。

通常,您无需为这两种方法烦恼,但是,如果您对磁盘上实际存储的内容抱有偏执是好事,则应按照说明进行两次调用。


2018年补遗。

请注意,具有缓存机制的磁盘现在比2013年更加普遍,因此现在涉及的缓存和缓冲区级别更高。我认为这些缓冲区也将由sync / flush调用处理,但我真的不知道。


10
当我使用该with file('blah') as fd: #dostuff构造时,我知道它保证关闭文件描述符。它也刷新或同步吗?
Marcin 2013年

3
@Marcin:刷新,但不同步。
Alex I

8
fsync是原子性所必需的。您不能期望关闭文件,重新打开文件并找到fsync中间没有中间内容的内容。它通常可以工作,但是在带有ext4和默认挂载选项的linux上不起作用。也fsync不能保证真正使磁铁翻转到盘子上,因为:1:可以禁用fsync(通过笔记本电脑模式); 2:可能不指示硬盘内部缓冲冲洗。
v.oddou

1
如果文件是由另一个进程写入的,是否有任何方法可以刷新所有文件的操作系统缓冲区?
Nacht 2014年

1
fsync 比较昂贵。通常,您并不是在编写需要100%ACID兼容性和持久性才能进行磁盘访问的关键任务软件,如果您这样做的话,您可能会痛苦地意识到这一点,并且应该了解获得这些保证所应采取的步骤。调用fsync将等待发生物理磁盘访问以将数据写入磁盘,而刷新和关闭将仅等待将数据移至高速缓存中。速度差可能约为几个数量级。
拉瑟五世·卡尔森


7

它刷新内部缓冲区,这应该导致操作系统将缓冲区写出到文件中。[1] 除非您另行配置,否则Python使用操作系统的默认缓冲。

但是有时OS仍然选择不合作。尤其是在Windows / NTFS中具有诸如写入延迟之类的奇妙功能。基本上清除了内部缓冲区,但OS缓冲区仍保持不变。因此,os.fsync()在这种情况下,您必须告诉操作系统将其写入磁盘。

[1] http://docs.python.org/library/stdtypes.html


0

基本上,flush()清除RAM缓冲区,其真正功能是让您随后继续写入它-但不应将其视为最佳/最安全的文件写入功能。这将冲刷您的RAM,以获取更多数据,仅此而已。如果要确保安全地将数据写入文件,请改用close()。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.