Python多久刷新一次文件?

288
  1. Python 多久刷新一次文件?
  2. Python 多久刷新一次标准输出?

(1) 我不确定。

(2) 对于 Python,我认为它在每个新行后都会刷新标准输出。但是,如果你将标准输出重定向到文件,它是否会刷新得更频繁呢?

5个回答

407

Python在进行文件操作时,默认使用操作系统的缓冲方式,除非您进行配置。您可以指定缓冲区大小、无缓冲或行缓冲。

例如,open函数接受一个缓冲区大小参数。

http://docs.python.org/library/functions.html#open

"可选的缓冲区参数用于指定文件所需的缓冲区大小:"

  • 0表示无缓冲,
  • 1表示行缓冲,
  • 任何其他正数值表示使用大约该大小的缓冲区。
  • 负缓冲意味着使用系统默认值,通常对于tty设备是行缓冲,对于其他文件是完全缓冲的。
  • 如果省略,则使用系统默认值。

代码:

bufsize = 0
f = open('file.txt', 'w', buffering=bufsize)

34
对于“行缓冲”的部分给一个赞。这正是我所寻找的,并且它完美地工作。 - rein
3
在使用Python 3.4.3时,当我执行open('file.txt', 'w', 1)时,我得到了正确的行缓冲。但是如果我使用更大的值(我想用open('file.txt', 'w', 512)),它会缓冲完整的8192字节的io.DEFAULT_BUFFER_SIZE。这是Python的bug、Linux的bug还是ID10t的bug? - Bruno Bronosky
是否可以更改已打开的流的缓冲区?比如说,我想让 stdout 以行缓冲的方式工作,无论它是在控制台还是被重定向到文件中。 - Mikhail T.
2
@CharlieParker 当你在文件句柄上调用 write() 函数时,输出会被缓存到内存中并累积,直到缓存已满...此时缓存将被 "flushed"(即将内容从缓存写入文件)。您可以通过在文件句柄上调用 flush() 方法来显式刷新缓存。 - Corey Goldberg
6
请注意,无缓冲(0)仅在二进制模式下可用,而行缓冲(1)仅在文本模式下可用。 - ZaydH
显示剩余2条评论

203

你还可以通过编程的方式使用flush()方法强制将缓冲区刷新到文件中。

with open('out.log', 'w+') as f:
    f.write('output is ')
    # some work
    s = 'OK.'
    f.write(s)
    f.write('\n')
    f.flush()
    # some other work
    f.write('done\n')
    f.flush()

当使用 tail -f 跟踪输出文件时,我发现这很有用。


76
文档中的说明:注意:flush()并不一定会将文件的数据写入磁盘。使用flush()之后再使用os.fsync()以确保这种行为。 - bobismijnnaam
2
@bobismijnnaam 下次请链接到相关文档。我能找到的唯一参考资料是来自 https://github.com/jprzywoski/python-reference/blob/master/source/docs/file/flush.rst ,但我不知道那是谁。 - Bruno Bronosky
8
@Bruno Bronosky 说得好。文档: 注意:flush() 不一定将文件数据写入磁盘。使用 flush() 后跟 os.fsync() 来确保这种行为。 - bobismijnnaam
4
我困惑的是术语“flushing”的含义。我们为什么需要它?它有什么作用?我为什么要关心它? - Charlie Parker
2
@CharlieParker 当你写入时,你是写入到 RAM 中的文件副本(部分),这可能不会立即保存到磁盘上。这样可以提高性能,但如果该副本从未被写入(磁盘移除、操作系统崩溃等),则可能导致数据丢失。flush() 告诉 Python 立即将缓冲区写回磁盘。(然后,os.fsync() 告诉操作系统也这样做。有许多层缓冲区...) - Rena
显示剩余2条评论

15

你还可以通过从 io 模块调用只读的 DEFAULT_BUFFER_SIZE 属性来检查默认缓冲区大小。

import io
print (io.DEFAULT_BUFFER_SIZE)

1
谢谢!知道Python将其设置为操作系统定义很好,但这有助于找出操作系统预定义的内容是什么。 - Cometsong

14

我不确定这是否也适用于Python,但我认为它取决于您运行的操作系统。

例如,在Linux上,终端输出在换行符时会刷新缓冲区,而对于文件输出,则只有在缓冲区已满时才会刷新(默认情况下)。 这是因为刷新缓冲区的次数越少越高效,并且如果在文件中未在换行符上刷新输出,用户可能不太容易注意到。

如果需要,您可能能够自动刷新输出。

编辑:我认为您可以按照此方式(基于此处)在Python中进行自动刷新。

#0 means there is no buffer, so all output
#will be auto-flushed
fsock = open('out.log', 'w', 0)
sys.stdout = fsock
#do whatever
fsock.close()

2
以下是另一种方法,由OP自行选择喜欢的方法。
在任何其他代码之前,在__init__.py文件中包含以下代码,使用print打印的消息和任何错误将不再记录到Ableton的Log.txt文件中,而是记录到您的磁盘上的单独文件中:
import sys

path = "/Users/#username#"

errorLog = open(path + "/stderr.txt", "w", 1)
errorLog.write("---Starting Error Log---\n")
sys.stderr = errorLog
stdoutLog = open(path + "/stdout.txt", "w", 1)
stdoutLog.write("---Starting Standard Out Log---\n")
sys.stdout = stdoutLog

(对于Mac电脑,请将#username#更改为您的用户文件夹名称。在Windows上,您的用户文件夹路径格式将不同)
当您使用一个能够在磁盘上的文件发生变化时刷新其内容的文本编辑器(例如Mac的TextEdit不能但TextWrangler可以)打开文件后,您会看到实时更新的日志。
致谢:这段代码大部分来自Nathan Ramella的liveAPI控制表面脚本。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接