如何刷新打印功能的输出?

2024-11-21 08:33:00
admin
原创
38
摘要:问题描述:如何强制 Pythonprint函数将缓冲输出刷新到屏幕?另请参阅: 如果目标是全面改变缓冲行为,则禁用输出缓冲print。这个问题是关于在特定调用之后明确刷新输出,即使输出仍在缓冲中。对于重复的结束语:如果初学者问了一个关于尝试在不使用换行符的情况下立即显示输出的问题,请使用 为什么在末尾没有换行...

问题描述:

如何强制 Pythonprint函数将缓冲输出刷新到屏幕?


另请参阅: 如果目标是全面改变缓冲行为,则禁用输出缓冲print。这个问题是关于在特定调用之后明确刷新输出,即使输出仍在缓冲中。

对于重复的结束语:如果初学者问了一个关于尝试在不使用换行符的情况下立即显示输出的问题,请使用 为什么在末尾没有换行符的情况下打印输出不会立即显示在终端中?来结束问题。当前的问题不够好,因为提问的人可能没有缓冲或刷新的概念;另一个问题旨在首先解释这些概念,而这个问题是关于技术细节的。


解决方案 1:

在 Python 3 中,print可以采用可选flush参数:

print("Hello, World!", flush=True)

在 Python 2 中,调用后print执行以下操作:

import sys
sys.stdout.flush()

默认情况下,print打印到(有关文件对象sys.stdout的更多信息,请参阅文档)。

解决方案 2:

您可以使用命令行标志更改刷新行为-u,例如python -u script.py

-u :无缓冲二进制 stdout 和 stderr;此外,PYTHONUNBUFFERED=x 请参阅手册页以了解有关 '-u' 相关的内部缓冲的详细信息

这是相关文档。

解决方案 3:

从 Python 3.3 开始,您可以强制普通print()函数刷新而无需使用sys.stdout.flush();只需将“flush”关键字参数设置为 true。摘自文档:

打印(*对象,sep =' ',end ='\ n',file = sys.stdout,flush = False)

将对象打印到流文件,以 sep 分隔并后跟 end。sep、end 和 file(如果存在)必须作为关键字参数给出。

所有非关键字参数都转换为字符串(如 str() 一样)并写入流中,以 sep 分隔,后跟 end。sep 和 end 都必须是字符串;它们也可以是 None,这意味着使用默认值。如果没有提供对象,print() 将只写入 end。

file 参数必须是具有 write(string) 方法的对象;如果不存在或为 None,则将使用 sys.stdout。输出是否缓冲通常由文件决定,但如果 flush 关键字参数为 true,则强制刷新流。

解决方案 4:

如何刷新 Python 打印的输出?

我建议采取五种方法来实现这一点:

  • 在 Python 3 中,调用print(..., flush=True)(flush 参数在 Python 2 的 print 函数中不可用,并且没有 print 语句的类似物)。

  • 调用file.flush()输出文件(我们可以包装 Python 2 的打印函数来执行此操作),例如,sys.stdout

  • 将其应用于模块中每个带有部分函数的打印函数调用,

print = partial(print, flush=True)并应用于模块全局。

  • -u将此应用于传递给解释器命令的标志 () 的进程

  • 将其应用于您环境中的每个 python 进程PYTHONUNBUFFERED=TRUE(并取消设置变量以撤消此操作)。

Python 3.3+

flush=True使用 Python 3.3 或更高版本,您只需向函数提供关键字参数即可print

print('foo', flush=True) 

Python 2(或低于 3.3)

他们没有将flush参数反向移植到 Python 2.7,因此,如果您使用的是 Python 2(或低于 3.3),并且想要与 2 和 3 兼容的代码,我建议使用以下兼容代码。(请注意,导入__future__必须位于/非常“靠近模块顶部”):

from __future__ import print_function
import sys

if sys.version_info[:2] < (3, 3):
    old_print = print
    def print(*args, **kwargs):
        flush = kwargs.pop('flush', False)
        old_print(*args, **kwargs)
        if flush:
            file = kwargs.get('file', sys.stdout)
            # Why might file=None? IDK, but it works for print(i, file=None)
            file.flush() if file is not None else sys.stdout.flush()

上述兼容性代码将涵盖大多数用途,但需要更彻底的处理,请参阅six模块。

或者,您也可以在打印后调用file.flush(),例如使用 Python 2 中的 print 语句:

import sys
print 'delayed output'
sys.stdout.flush()

将一个模块中的默认值更改为flush=True

您可以在模块的全局范围内使用 functools.partial 来更改打印功能的默认值:

import functools
print = functools.partial(print, flush=True)

如果你看一下我们的新部分函数,​​至少在 Python 3 中:

>>> print = functools.partial(print, flush=True)
>>> print
functools.partial(<built-in function print>, flush=True)

我们可以看到它像平常一样工作:

>>> print('foo')
foo

我们实际上可以覆盖新的默认值:

>>> print('foo', flush=False)
foo

再次注意,这只会改变当前的全局范围,因为当前全局范围上的打印名称将掩盖内置print函数(或者,如果在 Python 2 中使用兼容性函数,则在当前全局范围内取消引用兼容性函数)。

如果您想在函数内部而不是在模块的全局范围内执行此操作,则应该给它一个不同的名称,例如:

def foo():
    printf = functools.partial(print, flush=True)
    printf('print stuff like this')

如果在函数中将其声明为全局变量,则会在模块的全局命名空间中对其进行更改,因此您应该将其放在全局命名空间中,除非该特定行为正是您想要的。

更改流程的默认设置

我认为这里最好的选择是使用-u标志来获取无缓冲输出。

$ python -u script.py

或者

$ python -um package.module

来自文档:

强制 stdin、stdout 和 stderr 完全不缓冲。在重要的系统上,还将 stdin、stdout 和 stderr 置于二进制模式。

请注意,file.readlines() 和文件对象(用于 sys.stdin 中的行)中有内部缓冲,不受此选项的影响。要解决此问题,您需要在 while 1: 循环内使用 file.readline()。

更改 shell 操作环境的默认设置

如果将环境变量设置为非空字符串,则可以为环境中的所有 Python 进程或从环境继承的环境中获取此行为:

例如,在Linux或OSX中:

$ export PYTHONUNBUFFERED=TRUE

或 Windows:

C:SET PYTHONUNBUFFERED=TRUE

来自文档:

PYTHONUNBUFFED 库

如果将其设置为非空字符串,则相当于指定 -u 选项。


附录

这是 Python 2.7.12 中打印函数的帮助 - 请注意没有参数 flush

>>> from __future__ import print_function
>>> help(print)
print(...)
    print(value, ..., sep=' ', end='
', file=sys.stdout)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file: a file-like object (stream); defaults to the current sys.stdout.
    sep:  string inserted between values, default a space.
    end:  string appended after the last value, default a newline.

解决方案 5:

另外,正如这篇博客文章所建议的那样,可以sys.stdout在非缓冲模式下重新打开:

sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

每次stdout.writeandprint操作之后都会自动刷新。

解决方案 6:

在 Python 3.x 中,该print()功能得到了扩展:

print(*objects, sep=' ', end='
', file=sys.stdout, flush=False)

因此,您只需执行以下操作即可:

print("Visiting toilet", flush=True)

Python 文档条目

解决方案 7:

使用-u命令行开关是可行的,但有点笨拙。这意味着如果用户在不使用-u选项的情况下调用脚本,程序可能会出现错误行为。我通常使用自定义的stdout,如下所示:

class flushfile:
  def __init__(self, f):
    self.f = f

  def write(self, x):
    self.f.write(x)
    self.f.flush()

import sys
sys.stdout = flushfile(sys.stdout)

...现在您的所有print调用(隐式使用sys.stdout)都将被自动flush编辑。

解决方案 8:

使用非缓冲文件:

f = open('xyz.log', 'a', 0)

或者

sys.stdout = open('out.log', 'a', 0)

解决方案 9:

在 Python 3 中,你可以覆盖打印函数,并将默认设置为flush = True

def print(*objects, sep=' ', end='
', file=sys.stdout, flush=True):
    __builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush)

解决方案 10:

Dan 的想法不太可行:

#!/usr/bin/env python
class flushfile(file):
    def __init__(self, f):
        self.f = f
    def write(self, x):
        self.f.write(x)
        self.f.flush()

import sys
sys.stdout = flushfile(sys.stdout)

print "foo"

结果:

Traceback (most recent call last):
  File "./passpersist.py", line 12, in <module>
    print "foo"
ValueError: I/O operation on closed file

我认为问题在于它继承自文件类,而这实际上没有必要。根据 sys.stdout 的文档:

stdout 和 stderr 不需要是内置文件对象:任何对象只要具有接受字符串参数的 write() 方法都可以。

如此改变

class flushfile(file):

class flushfile(object):

使其工作正常。

解决方案 11:

这是我的版本,它也提供了 writelines() 和 fileno():

class FlushFile(object):
    def __init__(self, fd):
        self.fd = fd

    def write(self, x):
        ret = self.fd.write(x)
        self.fd.flush()
        return ret

    def writelines(self, lines):
        ret = self.writelines(lines)
        self.fd.flush()
        return ret

    def flush(self):
        return self.fd.flush

    def close(self):
        return self.fd.close()

    def fileno(self):
        return self.fd.fileno()

解决方案 12:

我在 Python 3.4 中这样做了:

'''To write to screen in real-time'''
message = lambda x: print(x, flush=True, end="")
message('I am flushing out now...')

解决方案 13:

我首先努力理解刷新选项是如何工作的。我想做一个“加载显示”,这是我找到的解决方案:

for i in range(100000):
    print('{:s}
'.format(''), end='', flush=True)
    print('Loading index: {:d}/100000'.format(i+1), end='')

第一行刷新先前的打印,第二行打印新的更新消息。我不知道这里是否存在单行语法。

解决方案 14:

在 python3 中,如上所述,设置print(..., flush=True)很棒,但对于给定的应用程序,您可能希望刷新每次打印:

def print(*args, **kwargs):
    __builtins__.print(*args, flush=True, **kwargs)
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   681  
  在项目管理领域,集成产品开发(IPD)流程以其高效、协同的特点,被众多企业视为提升产品竞争力的关键。IPD流程强调跨部门、跨职能的紧密合作,以确保产品从概念到市场各个环节的无缝衔接。然而,实现这一目标并非易事,它需要企业深刻理解并掌握IPD流程中的跨部门协作艺术。本文将深入探讨IPD流程中跨部门协作的三个关键点,旨在为...
IPD项目管理咨询   9  
  掌握IPD流程图:提升团队协作的关键路径在当今快速变化的商业环境中,团队协作的效率与效果直接关系到项目的成功与否。集成产品开发(Integrated Product Development,简称IPD)作为一种先进的研发管理理念,通过跨部门、跨领域的协同工作,能够显著提升产品开发的速度与质量。而IPD流程图,则是这一理...
IPD流程阶段   9  
  IPD流程概述:理解其核心价值与实施背景集成产品开发(Integrated Product Development,简称IPD)是一种先进的产品开发管理理念,它强调跨部门协作、市场导向和快速响应变化的能力。IPD流程不仅关注产品本身的技术创新,更注重将市场、研发、生产、销售等各个环节紧密集成,以实现产品从概念到市场的高...
华为IPD是什么   7  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程以其跨部门协作、高效决策和快速响应市场变化的特点,被众多企业视为提升竞争力的关键。然而,实践IPD流程并非易事,项目管理中的种种错误往往阻碍了其效果的充分发挥。本文旨在深入探讨如何在实施IPD流程时避免这些常见错误,...
IPD框架   7  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用