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

gee*_*eek 124 python io fsync output-buffering

我在文件对象的Python 文档中找到了这个:

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

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

ang*_*son 206

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

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

内部缓冲区是由您编程的运行时/库/语言创建的缓冲区,旨在通过避免每次写入的系统调用来加快速度.相反,当您写入文件对象时,您会写入其缓冲区,并且只要缓冲区填满,就会使用系统调用将数据写入实际文件.

但是,由于操作系统缓冲区,这可能并不意味着数据被写入磁盘.它可能只是意味着数据从运行时维护的缓冲区复制到操作系统维护的缓冲区中.

如果您写了一些内容,并且它最终在缓冲区中(仅限),并且电源被切断到您的机器,那么当机器关闭时,该数据不在磁盘上.

因此,为了帮助您拥有flushfsync方法,在各自的对象上.

第一个,flush只是将程序缓冲区中的任何数据写入实际文件.通常,这意味着数据将从程序缓冲区复制到操作系统缓冲区.

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

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

通常情况下,您不需要为任何一种方法而烦恼,但如果您处于一个对磁盘实际上最终结果存在偏执的情况,那么您应该按照指示进行两次调用.


2018年增编.

请注意,具有缓存机制的磁盘现在比2013年更常见,因此现在涉及更多级别的缓存和缓冲区.我假设这些缓冲区也将由同步/刷新调用处理,但我真的不知道.

  • 当我使用`with file('blah')作为fd:#dostuff`构造时,我知道它可以保证关闭文件描述符.它还会刷新还是同步? (10认同)
  • `fsync`是原子性所必需的.你不能期望关闭一个文件,重新打开它并找到你的内容而中间没有`fsync`.它通常可以工作,但它没有在linux上使用ext4和默认挂载选项.另外`fsync`不能保证真正磁铁翻转盘片上的铁,因为1:fsync可以被禁用(通过笔记本电脑模式),2:硬盘内部缓冲可能没有被指示刷新. (7认同)
  • 为什么有Nacht,只需使用`sync`命令 (4认同)
  • @Marcin:它会刷新,但不会同步. (3认同)
  • fsync *相对*昂贵。一般来说,您编写的任务关键型软件并不需要 100% ACID 合规性和磁盘访问的持久性,如果您这样做,您可能会痛苦地意识到这一点,并且应该了解可以采取哪些步骤来获得这些保证。调用 fsync 将等待发生物理磁盘访问以将数据写入磁盘,而刷新和关闭只会等待数据移动到缓存内存。速度差距恐怕有几个数量级。 (2认同)

Ign*_*ams 10

因为操作系统可能不会这样做.刷新操作强制将文件数据放入RAM中的文件高速缓存中,从那里开始实际将操作系统发送到磁盘.

  • 你是对的,但实际上``实际上是相对的:如果目标设备启用了写缓存,当`os.fsync()`返回时,数据可能没有达到实际的盘片/芯片. (6认同)

Dan*_*Dan 6

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

但有时操作系统仍然选择不合作.尤其是像Windows/NTFS中的写延迟这样的精彩内容.基本上内部缓冲区已刷新,但OS缓冲区仍然保持不变.因此,os.fsync()在这些情况下,您必须告诉操作系统将其写入磁盘.

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