【问题标题】:How to check if output buffering is enabled in Python如何检查是否在 Python 中启用了输出缓冲
【发布时间】:2016-09-01 19:17:22
【问题描述】:

在 Python 中有很多方法可以关闭输出缓冲:Disable output buffering

让我好奇的是,我怎么知道输出缓冲真的已经关闭了?检查它的最佳和简单方法是什么?

【问题讨论】:

  • 这真的很有趣。不过我怀疑这根本不可能,因为sys 是 C 模块,除了接口提供给您的功能之外,您无能为力。
  • 也许有更简单的方法?如果它打开或关闭,我们会得到什么明显的区别?如果没有区别,我们就不会关心它,对吧?它可能需要一个GIF来解释。我什至认为一张图片还不够。
  • 没有必要关心,真的。只要您知道何时需要刷新它,您就可以调用sys.stdout.flush(),无论缓冲是打开还是关闭都可以正常工作。在某些任务中,按时刷新可能很重要,例如查看我对stackoverflow.com/questions/39255498/… 的回答,但您不需要知道数据是否被缓冲。这只是一个有趣的发现,但我认为在这种情况下你可以运行一个实验。
  • 我知道。这是出于教育目的,因为我要进行的测试强调输出缓冲的重要性

标签: python python-2.7 output buffer output-buffering


【解决方案1】:

我用 Python 3.8 在 Linux 上测试了 stdout 缓冲,发现 Python3 的输出缓冲区可以检测它是否在终端(“TTY”)上运行,在这种情况下,打印函数的输出会立即显示, 否则输出会延迟到缓冲区满或脚本退出。例如,如果标准输出通过管道传输,它将决定它不在 TTY 上。 (抱歉,我不知道在 Windows 上会发生什么。)

当然,可以使用“flush=True”打印参数来防止这种输出延迟。也可以通过使用 Python3 的“-u”命令行参数禁用缓冲,或通过设置 shell 环境变量 PYTHONUNBUFFERED=true 来防止这种情况,在这种情况下,缓冲区将被直接 FileIO 替换。

所有这些都可以在 Python3 中通过查询 sys.stdout.buffer 来检测,如下所示:

#!/usr/bin/env python3
import sys
print("Name: ", type(sys.stdout.buffer).__name__)
print("TTY? ", sys.stdout.buffer.isatty())

这个脚本在各种条件下的输出是:

$ myscript.py # Displays immediately
Name:  BufferedWriter
TTY?  True

$ myscript.py | tee # Waits for script exit because of pipe
Name:  BufferedWriter
TTY?  False

$ python3 -u myscript.py # Displays immediately
Name:  FileIO
TTY?  True

$ python3 -u myscript.py | tee # Also displays immediately despite pipe
Name:  FileIO
TTY?  False

编辑:也可以使用以下 shebang 禁用缓冲(假设脚本名称在 shell 命令中没有以“python3”为前缀。)

#!/usr/bin/env -S python3 -u

【讨论】:

    【解决方案2】:

    试试这个:$ python myscript.py | cat

    如果没有缓冲,脚本的输出将立即显示在终端上。否则它将被cat 缓冲,直到发生刷新,或者由您的脚本触发或完成时。

    【讨论】:

      【解决方案3】:

      经过一些实验,我发现这种方法可以区分 python 是否在 stdout 上缓冲:

      import sys
      
      def is_stdout_buffered():
          # Print a single space + carriage return but no new-line (should have no visible effect)
          print " \r",
          # If the file position is a positive integer then stdout is buffered
          try:
              pos = sys.stdout.tell()
              if pos > 0:
                  return True
          except IOError:  # In some terminals tell() throws IOError if stdout is unbuffered
              pass
          return False
      

      我只在 Windows 上用 CMD、MinGW 和 Git Bash 测试过它。关键测试是 Git Bash,它默认为缓冲,除非你用 python -u 调用它,在这种情况下它是无缓冲的 (Cmd and Git bash have a different result when run a Python code)

      此检查可用于终端脚本的开头,以警告用户是否可能受到延迟输出的影响,例如如果没有刷新,则从打印语句中。

      【讨论】:

        猜你喜欢
        • 2011-08-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-29
        • 1970-01-01
        • 1970-01-01
        • 2017-03-08
        相关资源
        最近更新 更多