Python究竟是什么';s file.flush()在做什么?

Python究竟是什么';s file.flush()在做什么?,python,io,output-buffering,fsync,Python,Io,Output Buffering,Fsync,我在Python中发现: flush()不一定将文件的数据写入磁盘。使用flush()后跟os.fsync()以确保此行为 所以我的问题是:Python的flush到底在做什么?我原以为它强制将数据写入磁盘,但现在我发现它没有。为什么? 因为操作系统可能不这样做。刷新操作将文件数据强制放入RAM中的文件缓存中,从那里操作系统的任务是将其实际发送到磁盘。通常涉及两个缓冲级别: 内部缓冲区 操作系统缓冲区 内部缓冲区是由运行时/库/语言创建的缓冲区,用于通过避免每次写入的系统调用来加快速度。相反,当

我在Python中发现:

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


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

因为操作系统可能不这样做。刷新操作将文件数据强制放入RAM中的文件缓存中,从那里操作系统的任务是将其实际发送到磁盘。

通常涉及两个缓冲级别:

  • 内部缓冲区
  • 操作系统缓冲区
  • 内部缓冲区是由运行时/库/语言创建的缓冲区,用于通过避免每次写入的系统调用来加快速度。相反,当您写入文件对象时,您会写入其缓冲区,每当缓冲区填满时,数据就会使用系统调用写入实际文件

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

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

    因此,为了帮助实现这一点,您在各自的对象上使用了
    flush
    fsync
    方法

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

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

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

    通常,您不需要为这两种方法费心,但如果您处于这样一种场景中,对磁盘上的实际结果抱有妄想是一件好事,那么您应该按照指示进行两次调用


    2018年补遗


    请注意,具有缓存机制的磁盘现在比2013年更为常见,因此现在涉及到更多级别的缓存和缓冲区。我假设这些缓冲区也会由sync/flush调用来处理,但我真的不知道。

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

    但有时操作系统仍然选择不合作。特别是在Windows/NTFS中的写延迟之类的美妙事情上。基本上,内部缓冲区已刷新,但操作系统缓冲区仍保留着它。因此,在这种情况下,您必须告诉操作系统使用
    OS.fsync()
    将其写入磁盘


    [1]

    基本上,flush()会清除RAM缓冲区,它的真正功能是允许您在以后继续写入—但它不应该被认为是最好/最安全的文件写入功能。它正在刷新你的RAM以获得更多的数据,仅此而已。若要确保数据安全写入文件,请改用close()

    你是对的,但是实际上
    在这里是相对的:如果目标设备启用了写缓存,那么当
    os.fsync()
    返回时,数据可能没有到达实际的磁盘/芯片。当我使用
    和file('blah')作为fd:#dostuff
    构造时,我知道它保证关闭文件描述符。它也刷新还是同步?@Marcin:它刷新,但不同步。
    fsync
    是原子性所必需的。您不能期望关闭文件,重新打开它并在中间没有找到<代码> fSycs<代码>找到您的内容。它通常可以工作,但在linux上(例如使用ext4和默认装载选项)就不能工作。另外,
    fsync
    也不能保证真的能用磁铁翻转盘片上的熨斗,因为1:fsync可以被禁用(通过笔记本电脑模式),2:硬盘内部缓冲可能不会被指示刷新。有没有办法刷新操作系统对所有文件的缓冲区,如果文件是由另一个进程写入的,则fsync的成本相对较高。一般来说,您编写的任务关键型软件不需要100%的ACID遵从性和磁盘访问的持久性,如果您这样做,您可能会痛苦地意识到这一点,并且应该意识到您可以采取哪些步骤来获得这些保证。调用fsync将等待发生物理磁盘访问以将数据写入磁盘,而刷新和关闭将只等待数据移动到缓存中。速度差可能是几个数量级。