如何刷新Python打印输出?

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

这不是禁用输出缓冲的重复 – 链接的问题是尝试无缓冲的输出,而这是更一般的。 这个问题的最佳答案是太强大了,或者涉及到这个问题(他们不是很好的答案),这个问题可以在Google上find一个相对的新手。

运行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)

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

所有非关键字参数都被转换为像str()那样的string,并写入到stream中,由sep分隔,然后是end。 sep和end都必须是string; 他们也可以是None,这意味着使用默认值。 如果没有给出对象,print()将只写结束。

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

也正如在这个博客中所build议的,可以以非缓冲模式重新打开sys.stdout

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

每个stdout.writeprint操作都会自动刷新。

如何刷新Python打印输出?

我build议五种做法:

  • 使用flush=True参数调用print。
  • 调用输出文件file.flush() (我们可以包装python 2的打印function来做到这一点),例如, sys.stdout
  • 将其应用于具有部分function的模块中的每个打印函数调用,
    print = partial(print, flush=True)应用于全局模块。
  • 将其应用于传递给解释器命令的标志( -u
  • 把它应用到你的环境中的每个python进程中, PYTHONUNBUFFERED=TRUE使用PYTHONUNBUFFERED=TRUE (并且取消设置这个variables来取消这个)。

Python 3.3+

使用Python 3.3或更高版本,您可以提供flush=True作为关键字参数给printfunction:

 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) 

如果你看看我们的新的部分函数,​​至less在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 

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

如果你想在一个函数中而不是在一个模块的全局范围内做这个,你应该给它一个不同的名字,例如:

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

如果你在一个函数中声明它是一个全局variables,那么你需要在模块的全局名称空间中改变它,所以你应该把它放在全局名称空间中,除非这个特定的行为正是你想要的。

更改过程的默认值

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

 $ python -u script.py 

要么

 $ python -um package.module 

从文档 :

强制stdin,stdout和stderr完全无缓冲。 在重要的系统上,也可以把stdin,stdout和stderr放在二进制模式下。

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

更改shell操作环境的默认值

如果将环境variables设置为非空string,则可以为环境中的所有python进程或从环境inheritance的环境获取此行为:

例如在Linux或OSX中:

 $ export PYTHONUNBUFFERED=TRUE 

或Windows:

 C:\SET PYTHONUNBUFFERED=TRUE 

从文档 :

PYTHONUNBUFFERED

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


附录

下面是关于Python 2.7.12打印函数的帮助 – 请注意, 没有 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. 

使用-u命令行开关工作,但它有点笨拙。 这意味着如果用户调用没有-u选项的脚本,程序可能会错误地运行。 我通常使用一个自定义的stdout ,像这样:

 class flushfile(object): 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

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

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

要么

 sys.stdout = open('out.log', 'a', 0) 
 import sys print 'This will be output immediately.' sys.stdout.flush() 

丹的想法不太合适:

 #!/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 

我相信问题是它从文件类inheritance,这实际上是没有必要的。 根据sys.stdout的文档:

stdout和stderr不需要内置文件对象:只要有一个带有string参数的write()方法,任何对象都是可以接受的。

所以改变

 class flushfile(file): 

 class flushfile(object): 

使它工作得很好。

在Python 3.x中,它们扩展了print()函数:

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

所以,你可以做:

print("Foo", flush=True)


Python文档条目

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

爱丹的解决scheme! 对于python3来说:

 import io,sys class flushfile: def __init__(self, f): self.f = f def write(self, x): self.f.write(x) self.f.flush() sys.stdout = flushfile(sys.stdout) 

我在Python 3.4中这样做了:

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

在Python 3中,您可以使用默认设置为flush = True来覆盖打印function

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