如何刷新打印功能的输出?
- 2024-11-21 08:33:00
- admin 原创
- 4
问题描述:
如何强制 Pythonprint
函数将缓冲输出刷新到屏幕?
另请参阅: 如果目标是全面改变缓冲行为,则禁用输出缓冲print
。这个问题是关于在特定调用之后明确刷新输出,即使输出仍在缓冲中。
对于重复的结束语:如果初学者问了一个关于尝试在不使用换行符的情况下立即显示输出的问题,请使用 为什么在末尾没有换行符的情况下打印输出不会立即显示在终端中?来结束问题。当前的问题不够好,因为提问的人可能没有缓冲或刷新的概念;另一个问题旨在首先解释这些概念,而这个问题是关于技术细节的。
解决方案 1:
在 Python 3 中,print
可以采用可选flush
参数:
print("Hello, World!", flush=True)
在 Python 2 中,调用后print
执行以下操作:
import sys
sys.stdout.flush()
默认情况下,print
打印到(有关文件对象sys.stdout
的更多信息,请参阅文档)。
解决方案 2:
您可以使用命令行标志更改刷新行为-u
,例如python -u script.py
。
-u :无缓冲二进制 stdout 和 stderr;此外,PYTHONUNBUFFERED=x 请参阅手册页以了解有关 '-u' 相关的内部缓冲的详细信息
这是相关文档。
解决方案 3:
从 Python 3.3 开始,您可以强制普通print()
函数刷新而无需使用sys.stdout.flush()
;只需将“flush”关键字参数设置为 true。摘自文档:
打印(*对象,sep =' ',end ='\ n',file = sys.stdout,flush = False)
将对象打印到流文件,以 sep 分隔并后跟 end。sep、end 和 file(如果存在)必须作为关键字参数给出。
所有非关键字参数都转换为字符串(如 str() 一样)并写入流中,以 sep 分隔,后跟 end。sep 和 end 都必须是字符串;它们也可以是 None,这意味着使用默认值。如果没有提供对象,print() 将只写入 end。
file 参数必须是具有 write(string) 方法的对象;如果不存在或为 None,则将使用 sys.stdout。输出是否缓冲通常由文件决定,但如果 flush 关键字参数为 true,则强制刷新流。
解决方案 4:
如何刷新 Python 打印的输出?
我建议采取五种方法来实现这一点:
在 Python 3 中,调用
print(..., flush=True)
(flush 参数在 Python 2 的 print 函数中不可用,并且没有 print 语句的类似物)。调用
file.flush()
输出文件(我们可以包装 Python 2 的打印函数来执行此操作),例如,sys.stdout
将其应用于模块中每个带有部分函数的打印函数调用,
print = partial(print, flush=True)
并应用于模块全局。
-u
将此应用于传递给解释器命令的标志 () 的进程将其应用于您环境中的每个 python 进程
PYTHONUNBUFFERED=TRUE
(并取消设置变量以撤消此操作)。
Python 3.3+
flush=True
使用 Python 3.3 或更高版本,您只需向函数提供关键字参数即可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
来自文档:
PYTHONUNBUFFED 库
如果将其设置为非空字符串,则相当于指定 -u 选项。
附录
这是 Python 2.7.12 中打印函数的帮助 - 请注意没有参数 flush
:
>>> from __future__ import print_function
>>> help(print)
print(...)
print(value, ..., sep=' ', end='
', 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.
解决方案 5:
另外,正如这篇博客文章所建议的那样,可以sys.stdout
在非缓冲模式下重新打开:
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
每次stdout.write
andprint
操作之后都会自动刷新。
解决方案 6:
在 Python 3.x 中,该print()
功能得到了扩展:
print(*objects, sep=' ', end='
', file=sys.stdout, flush=False)
因此,您只需执行以下操作即可:
print("Visiting toilet", flush=True)
Python 文档条目
解决方案 7:
使用-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
编辑。
解决方案 8:
使用非缓冲文件:
f = open('xyz.log', 'a', 0)
或者
sys.stdout = open('out.log', 'a', 0)
解决方案 9:
在 Python 3 中,你可以覆盖打印函数,并将默认设置为flush = True
def print(*objects, sep=' ', end='
', file=sys.stdout, flush=True):
__builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush)
解决方案 10:
Dan 的想法不太可行:
#!/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):
使其工作正常。
解决方案 11:
这是我的版本,它也提供了 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()
解决方案 12:
我在 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:
我首先努力理解刷新选项是如何工作的。我想做一个“加载显示”,这是我找到的解决方案:
for i in range(100000):
print('{:s}
'.format(''), end='', flush=True)
print('Loading index: {:d}/100000'.format(i+1), end='')
第一行刷新先前的打印,第二行打印新的更新消息。我不知道这里是否存在单行语法。
解决方案 14:
在 python3 中,如上所述,设置print(..., flush=True)
很棒,但对于给定的应用程序,您可能希望刷新每次打印:
def print(*args, **kwargs):
__builtins__.print(*args, flush=True, **kwargs)
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件