代码之家  ›  专栏  ›  技术社区  ›  Adam Matan

在Python中close()表示flush()吗?

  •  30
  • Adam Matan  · 技术社区  · 15 年前

    close() 对文件对象的操作意味着 flush()

    4 回复  |  直到 10 年前
        1
  •  34
  •   tshepang Arrie    10 年前

    对。它使用底层 close() 为你做这些的函数( source ).

        2
  •  18
  •   Douglas Leeder    15 年前

    close() flush() 无法确保磁盘上的数据实际上是安全的。它只是确保操作系统的数据==没有在进程内缓冲。

        3
  •  3
  •   Felix D. cruftex    7 年前

    in the official documentation ,但在Python2中已经是这样了(参见 Martin's answer ).

        4
  •  0
  •   Thomas Guyot-Sionnest    4 年前

    作为对这个问题的补充,是的,python会在关闭前进行刷新,但是如果您想确保数据正确写入磁盘,这是不够的。

    外部3 具有 data=ordered (默认),以及 外部4 在添加对写关闭重命名模式的检测和在这些模式上的元数据之前同步数据之前,最初发现了许多应用程序缺陷 [1] ).

    # Write destfile, using a temporary name .<name>_XXXXXXXX
    base, name = os.path.split(destfile)
    tmpname = os.path.join(base, '.{}_'.format(name))  # This is the tmpfile prefix
    with tempfile.NamedTemporaryFile('w', prefix=tmpname, delete=False) as fd:
        # Replace prefix with actual file path/name
        tmpname = str(fd.name)
    
        try:
            # Write fd here... ex:
            json.dumps({}, fd)
    
            # We want to fdatasync before closing, so we need to flush before close anyway
            fd.flush()
            os.fdatasync(fd)
    
            # Since we're using tmpfile, we need to also set the proper permissions
            if os.path.exists(destfile):
                # Copy destination file's mask
                os.fchmod(fd.fileno, os.stat(destfile).st_mode)
            else:
                # Set mask based on current umask value
                umask = os.umask(0o22)
                os.umask(umask)
                os.fchmod(fd.fileno, 0o666 & ~umask)  # 0o777 for dirs and executable files)
    
            # Now we can close and rename the file (overwriting any existing one)
            fd.close()
            os.rename(tmpname, destfile)
        except:
            # On error, try to cleanup the temporary file
            try:
                os.unlink(tmpname)
            except OSError:
                pass
            raise
    

    如果Python能提供简单的方法来解决这个问题,那就太好了。。。同时,我想如果您关心数据的一致性,那么最好在较低的级别上真正了解正在发生的事情,特别是因为不同的操作系统和文件系统之间存在许多差异。

    还要注意的是,这并不能保证写入的数据可以恢复,只保证您将获得数据的一致副本(旧的或新的)。为了确保在返回时安全地写入和访问新数据,您需要使用 os.fsync(...)

        5
  •  -8
  •   przemek    12 年前

    filehandle.close不一定刷新。出人意料的是,filehandle.flush也帮不上忙——当Python运行时,它仍然会被困在OS缓冲区中。观察这个会话,我在其中写入了一个文件,关闭了它,并在shell命令提示符下按Ctrl-Z键并检查了该文件:

    $  cat xyz
    ghi
    $ fg
    python
    
    >>> x=open("xyz","a")
    >>> x.write("morestuff\n")
    >>> x.write("morestuff\n")
    >>> x.write("morestuff\n")
    >>> x.flush
    <built-in method flush of file object at 0x7f58e0044660>
    >>> x.close
    <built-in method close of file object at 0x7f58e0044660>
    >>> 
    [1]+  Stopped                 python
    $ cat xyz
    ghi
    

    随后,我可以重新打开该文件,这必然会同步该文件(因为在本例中,我是在append模式下打开它的)。正如其他人所说,sync syscall(可从操作系统包获得)应该将所有缓冲区刷新到磁盘,但它可能会影响整个系统的性能(它会同步系统上的所有文件)。