如何强制Python的打印功能输出到屏幕?
这不是Disable output buffering的重复 - 链接的问题是尝试无缓冲输出,而这是更一般的。这个问题的最佳答案太强大或涉及到这个问题(他们不是很好的答案),这个问题可以在谷歌上找到一个相对新手。
答案 0 :(得分:1207)
import sys
sys.stdout.flush()
默认情况下, print
会打印到sys.stdout
。
Python 2
Python 3
print()
sys.stdout
io.IOBase.flush()
(sys.stdout
从flush
继承io.IOBase
方法)答案 1 :(得分:322)
运行python -h
,我看到命令行选项:
-u:无缓冲的二进制stdout和stderr; PYTHONUNBUFFERED = x 有关'-u'
的内部缓冲的详细信息,请参见手册页
这是relevant doc。
答案 2 :(得分:293)
从Python 3.3开始,您可以强制执行普通print()
函数,而无需使用sys.stdout.flush()
;只需将“flush”关键字参数设置为true即可。来自the documentation:
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,则强制刷新流。
答案 3 :(得分:147)
如何刷新Python打印输出?
我建议采取五种方法:
print(..., flush=True)
(在Python 2的print函数中没有flush参数,并且print语句没有类似的东西。)file.flush()
(我们可以使用python 2的print函数来执行此操作),例如,sys.stdout
print = partial(print, flush=True)
已应用于全局模块。-u
)的进程
PYTHONUNBUFFERED=TRUE
将此应用于您环境中的每个python进程(并取消设置该变量以撤消此操作)。使用Python 3.3或更高版本,您只需提供flush=True
作为print
函数的关键字参数:
print('foo', flush=True)
他们没有将flush
参数反向移植到Python 2.7所以如果您使用的是Python 2(或者小于3.3),并且希望代码兼容2和3,我可以建议以下兼容性代码。 (请注意,__future__
导入必须位于/ {非常“靠近top of your module”):
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()
上述兼容性代码将涵盖大多数用途,但对于更彻底的处理,see the six
module。
或者,您可以在打印后调用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
来自docs:
强制stdin,stdout和stderr完全无缓冲。在重要的系统上,还将stdin,stdout和stderr置于二进制模式。
请注意,file.readlines()和文件对象(对于sys.stdin中的行)有内部缓冲,不受此选项的影响。要解决这个问题,你需要在while 1:loop中使用file.readline()。
如果将环境变量设置为非空字符串,则可以在环境中继承环境或环境中的所有python进程获取此行为:
例如,在Linux或OSX中:$ export PYTHONUNBUFFERED=TRUE
或Windows:
C:\SET PYTHONUNBUFFERED=TRUE
来自docs:
<强> PYTHONUNBUFFERED 强>
如果将其设置为非空字符串,则相当于指定-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.
答案 4 :(得分:67)
同样如this blog中所建议,可以在无缓冲模式下重新启动sys.stdout
:
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
之后,每个stdout.write
和print
操作都会自动刷新。
答案 5 :(得分:51)
使用Python 3.x,print()
函数已被扩展:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
所以,你可以这样做:
print("Visiting toilet", flush=True)
答案 6 :(得分:35)
使用-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
。
答案 7 :(得分:19)
为什么不尝试使用无缓冲的文件?
f = open('xyz.log', 'a', 0)
OR
sys.stdout = open('out.log', 'a', 0)
答案 8 :(得分:15)
import sys
print 'This will be output immediately.'
sys.stdout.flush()
答案 9 :(得分:13)
#!/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):
让它工作得很好。
答案 10 :(得分:8)
这是我的版本,它也提供了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()
答案 11 :(得分:7)
喜欢Dan的解决方案!对于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)
答案 12 :(得分:4)
我在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 :(得分:4)
在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)
答案 14 :(得分:1)
我首先要努力了解冲洗选项的工作方式。我想做一个“加载显示”,在这里找到了解决方法:
for i in range(100000):
print('{:s}\r'.format(''), end='', flush=True)
print('Loading index: {:d}/100000'.format(i+1), end='')
第一行刷新上一打印,第二行打印新的更新消息。我不知道这里是否存在单行语法。