如何强制Python的打印函数输出到屏幕?

这不是重复的 禁用输出缓冲 - 链接的问题正在尝试无缓冲的输出,虽然这是更一般的。该问题中的最佳答案对于这个问题来说太强大或太复杂(它们不是这个问题的好答案),并且相对新手可以在 Google 上找到这个问题。

有帮助吗?

解决方案

import sys
sys.stdout.flush()

print 默认情况下打印到 sys.stdout.

参考

蟒蛇2

蟒蛇3

其他提示

运行python -h,我看到命令行选项

  

-u:无缓冲的二进制stdout和stderr; PYTHONUNBUFFERED = x            有关'-u'

的内部缓冲的详细信息,请参见手册页

以下是相关文档

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

  

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

     

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

     

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

     

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

如何刷新Python print 的输出?

我建议采用五种方法来做到这一点:

  • 在Python 3中,调用 print(..., flush=True) (flush 参数在 Python 2 的 print 函数中不可用,并且 print 语句没有类似的东西)。
  • 称呼 file.flush() 在输出文件上(我们可以包装 python 2 的 print 函数来执行此操作),例如, sys.stdout
  • 将其应用于具有部分函数的模块中的每个打印函数调用,
    print = partial(print, flush=True) 应用于模块全局。
  • 将其应用到带有标志的进程(-u) 传递给解释器命令
  • 将其应用于您环境中的每个 python 进程 PYTHONUNBUFFERED=TRUE (并取消设置变量以撤消此操作)。

Python 3.3+

使用Python 3.3或更高版本,您只需提供 flush=True 作为关键字参数 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

来自 文档:

Python无缓冲

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


附录

这是 Python 2.7.12 中 print 函数的帮助 - 请注意,有 flush 争论:

>>> from __future__ import print_function
>>> help(print)
print(...)
    print(value, ..., sep=' ', end='\n', 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.

另外,如此博客所示,可以重新开启sys.stdout在无缓冲模式下:

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

之后将自动刷新每个stdout.writeprint操作。

使用Python 3.x,print()函数已被扩展:

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

所以,你可以这样做:

print("Visiting toilet", flush=True)

Python文档录入

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

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)

...现在,所有sys.stdout电话(隐含地使用flush)将自动<=>编辑。

为什么不尝试使用无缓冲的文件?

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

OR

sys.stdout = open('out.log', 'a', 0)
丹的想法并不奏效:

#!/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 needn <!>#8217;内置   文件对象:任何对象都可以接受   只要它有一个write()方法   这需要一个字符串参数。

如此改变

class flushfile(file):

class flushfile(object):

让它工作得很好。

这是我的版本,它也提供了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()

在Python 3中,您可以使用默认设置flush = True

覆盖打印功能
def print(*objects, sep=' ', end='\n', file=sys.stdout, flush=True):
    __builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush)

我在Python 3.4中这样做了:

'''To write to screen in real-time'''
message = lambda x: print(x, flush=True, end="")
message('I am flushing out now...')
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top