如何强制Python的打印功能输出到屏幕?
这不是禁用输出缓冲的重复- 链接的问题是尝试无缓冲输出,而这是更一般的.这个问题的最佳答案太强大或涉及到这个问题(他们不是很好的答案),这个问题可以在谷歌上找到一个相对新手.
print("Hello world!", flush=True)
默认打印打印到print
.
参考文献:
http://docs.python.org/reference/simple_stmts.html#the-print-statement
http://docs.python.org/library/sys.html
http://docs.python.org/library/stdtypes.html#file-objects
运行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打印输出?
我建议五种方法:
在Python 3中,调用print(..., flush=True)
(在Python 2的print函数中不提供flush参数,并且print语句没有模拟).
调用file.flush()
输出文件(我们可以包装python 2的print函数来执行此操作),例如,sys.stdout
将此
print = partial(print, flush=True)
应用于具有部分功能的模块中的每个打印函数调用,应用于模块全局.
使用-u
传递给interpreter命令的flag()将此应用于进程
将此应用于环境中的每个python进程PYTHONUNBUFFERED=TRUE
(并取消设置该变量以撤消此操作).
使用Python 3.3或更高版本,您只需提供函数flush=True
的关键字参数print
:
print('foo', flush=True)
他们没有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更改print函数的默认值:
import functools print = functools.partial(print, flush=True)
如果你看看我们的新的部分函数,至少在Python 3中:
>>> print = functools.partial(print, flush=True) >>> print functools.partial(, 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()和File Objects(对于sys.stdin中的行)中存在内部缓冲,不受此选项的影响.要解决此问题,您需要在while 1:循环中使用file.readline().
如果将环境变量设置为非空字符串,则可以对环境中继承的环境中的所有python进程获取此行为:
例如,在Linux或OSX中:
$ export PYTHONUNBUFFERED=TRUE
或Windows:
C:\SET PYTHONUNBUFFERED=TRUE
来自文档:
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.
同样如本博客所示,可以sys.stdout
在无缓冲模式下重新打开:
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
每个stdout.write
和print
操作后自动刷新.
使用Python 3.x,该print()
功能已得到扩展:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
所以,你可以这样做:
print("Visiting toilet", flush=True)
Python文档录入
使用-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
编辑.
为什么不尝试使用无缓冲的文件?
f = open('xyz.log', 'a', 0)
要么
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, inprint "foo" ValueError: I/O operation on closed file
我相信问题是它继承自文件类,实际上并不是必需的.根据sys.stdout的文档:
stdout和stderr不需要是内置文件对象:任何对象都是可接受的,只要它有一个带有字符串参数的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...')