如何刷新Python打印输出?
如何强制Python的打印function输出到屏幕?
这不是禁用输出缓冲的重复 – 链接的问题是尝试无缓冲的输出,而这是更一般的。 这个问题的最佳答案是太强大了,或者涉及到这个问题(他们不是很好的答案),这个问题可以在Google上find一个相对的新手。
import sys sys.stdout.flush()
打印默认打印到sys.stdout
。
参考文献:
运行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.write
和print
操作都会自动刷新。
如何刷新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
作为关键字参数给print
function:
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
再次注意,这只会改变当前的全局范围,因为当前全局范围的打印名称会掩盖内置的print
function(或者在当前的全局范围内,如果使用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)