python - Linux 和 Windows 上标准输出的缓冲差异

标签 python linux windows stdout

写入控制台时,Windows 和 Linux 上的 stdout 缓冲方式似乎有所不同。考虑这个小的 python 脚本:

import time
for i in xrange(10):
    time.sleep(1)
    print "Working" ,

在 Windows 上运行此脚本时,我们看到 Working 一个接一个地出现,中间等待了第二秒。在 Linux 上,我们必须等待 10 秒,然后整行立即出现。

如果我们将最后一行更改为 print "Working",则每一行也会在 Linux 上单独显示。

所以在 Linux 上,stdout 似乎是行缓冲的,而在 Windows 上根本不是。我们可以使用 -u 选项关闭缓冲(在这种情况下,Linux 上的脚本与 Windows 上的脚本具有相同的行为)。 documentation说:

-u Force stdin, stdout and stderr to be totally unbuffered.

所以实际上,它并没有说,如果没有 -u-选项,stdinstdout 会被缓冲。因此我的问题是:

  1. 在 Linux/Windows 上出现不同行为的原因是什么?
  2. 是否有某种保证,如果重定向到文件stdout 将被缓冲,无论是哪个操作系统?至少这似乎是 Windows 和 Linux 的情况。

我主要担心的不是(正如一些答案假设的那样)什么时候信息被刷新,而是如果 stdout 没有被缓冲,它可能会严重影响性能并且人们不应该依赖它。

编辑:可能值得注意的是,对于 Python3,Linux 和 Windows 的行为是相同的(但这并不奇怪,因为行为是由 的参数显式配置的print-方法)。

最佳答案

假设您正在谈论 CPython(很可能),这与底层 C 实现的行为有关。

ISO C 标准提到 (C11 7.21.3 Files/3) 三种模式:

  • 无缓冲(字符尽快出现);
  • 完全缓冲(缓冲区满时出现字符);和
  • 行缓冲(字符出现在换行输出中)。

其他触发器会导致字符出现(例如即使没有换行符输出也会填满缓冲区,在某些情况下请求输入或关闭流)但它们并不重要在你的问题的上下文中。

重要的是同一标准中的 7.21.3 Files/7:

As initially opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.

请注意那里的回旋余地。标准输出可以是行缓冲的或非缓冲的,除非实现确定它不是交互式设备。

在这种情况下(控制台),它一个交互式设备,因此不允许使用无缓冲的实现。它但是允许选择其他两种模式中的任何一种,这就是您看到差异的原因。

无缓冲输出会在您输出消息时立即看到消息(就像您的 Windows 行为一样)。行缓冲会延迟到换行符输出(您的 Linux 行为)。

如果你真的想确保你的消息在任何模式下都被刷新,只需自己刷新它们:

import time, sys
for i in xrange(10):
    time.sleep(1)
    print "Working",
    sys.stdout.flush()
print

关于保证在重定向到文件时输出将被缓冲,这将包含在我已经展示的标准的引号中。如果可以确定流正在使用非交互式设备,它将被完全缓冲。这不是绝对保证,因为它没有说明这是如何确定的,但如果任何实现无法解决这个问题,我会感到惊讶。

在任何情况下,您都可以测试特定的实现,只需重定向输出并监视文件以查看它是否在每个输出或结束时刷新一次。

关于python - Linux 和 Windows 上标准输出的缓冲差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45545810/

相关文章:

python - 中间用户在转发链中的作用

linux - arm-linux-gnueabi 跳过了 PWD 中的某些 header ?

c++ - 大数据 block 的 C++ 中的碎片 (Windows)

windows - 记事本打败了所有人?

linux - 在 Windows Server 2012 R2 WMF 4.0 上安装 DSC 资源 nxComputerManagement 和 nxNetworking

windows - 在 Windows 批处理脚本中的特殊字符的倍数之后截断文件名?

python - 多对多表和初始化字段

python - 将字典附加到列表 - 我看到类似行为的指针

python - 如何计算 pandas 中后续行的数量

java - 如何配置/减少 tcp 段大小