Python print函数输出刷新方法
技术背景
在Python中,print
函数的输出有时会被缓冲,这可能导致在某些情况下,输出不会立即显示在终端上。例如,在需要实时显示进度信息的程序中,就需要手动刷新输出,以确保信息能及时显示。
实现步骤
Python 3.3+
在Python 3.3及以上版本,可以直接在print
函数中使用flush=True
参数:
1
| print('foo', flush=True)
|
Python 2(或 < 3.3)
由于Python 2的print
函数没有flush
参数,若要实现兼容Python 2和3的代码,可以使用以下方式:
1 2 3 4 5 6 7 8 9 10 11
| 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) file.flush() if file is not None else sys.stdout.flush()
|
全局设置刷新
可以使用partial
函数将flush=True
应用到模块全局的print
函数:
1 2
| from functools import partial print = partial(print, flush=True)
|
使用命令行标志
在运行Python脚本时,可以使用-u
标志来实现无缓冲输出:
设置环境变量
在Linux或OSX系统中:
1
| export PYTHONUNBUFFERED=TRUE
|
在Windows系统中:
1
| SET PYTHONUNBUFFERED=TRUE
|
核心代码
Python 3.3+直接刷新
1
| print('实时输出信息', flush=True)
|
Python 2兼容代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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) file.flush() if file is not None else sys.stdout.flush()
print('兼容Python 2和3的输出', flush=True)
|
自定义FlushFile
类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| 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.fd.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()
import sys sys.stdout = FlushFile(sys.stdout) print('使用自定义类刷新输出')
|
最佳实践
实时进度显示
1 2
| for i in range(100): print(f'\r当前进度: {i}%', end='', flush=True)
|
重写print
函数
1 2 3 4
| def print(*args, **kwargs): __builtins__.print(*args, flush=True, **kwargs)
print('所有输出自动刷新')
|
常见问题
flushfile
类继承file
类报错
在Python 2中,若flushfile
类继承file
类,会出现ValueError: I/O operation on closed file
错误。解决方法是将其继承object
类:
1 2 3 4 5 6 7 8 9 10 11
| 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('修改后正常输出')
|
-u
标志可能导致行为不一致
使用-u
命令行标志时,如果用户在调用脚本时未使用该选项,程序可能会出现异常。可以使用自定义stdout
的方式来避免这个问题。