How to flush output of print function?
如何强制python的print函数输出到屏幕?
这不是禁用输出缓冲的副本-链接问题正在尝试未缓冲的输出,而这是更一般的。这个问题中的顶级答案对这个问题来说太强大或涉及太多(它们不是很好的答案),这个问题可以由一个相对的新手在谷歌上找到。
1 2 | import sys sys.stdout.flush() |
默认打印到
参考文献:
- http://docs.python.org/reference/simple_stmts.html打印语句
- http://docs.python.org/library/sys.html网站
- http://docs.python.org/library/stdtypes.html文件对象
运行
-u : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x
see man page for details on internal buffering relating to '-u'
这是相关的文件。
由于python 3.3,您可以强制正常的
print(*objects, sep=' ', end='
', file=sys.stdout, flush=False)Print objects to the stream file, separated by sep and followed by end. sep, end and file, if present, must be given as keyword arguments.
All non-keyword arguments are converted to strings like str() does and written to the stream, separated by sep and followed by end. Both sep and end must be strings; they can also be None, which means to use the default values. If no objects are given, print() will just write end.
The file argument must be an object with a write(string) method; if it is not present or None, sys.stdout will be used. Whether output is buffered is usually determined by file, but if the flush keyword argument is true, the stream is forcibly flushed.
How to flush output of Python print?
我建议采取五种方法:
- 在python 3中,调用
print(..., flush=True) (flush参数在python 2的print函数中不可用,并且print语句没有类似的参数)。 - 在输出文件上调用
file.flush() (我们可以包装python 2的print函数来完成此操作),例如,sys.stdout 。 - 将此应用于具有部分函数的模块中的每个打印函数调用,
print = partial(print, flush=True) 应用于模块全局。 - 将此应用于传递给解释器命令的标志(
-u 的进程 - 使用
PYTHONUNBUFFERED=TRUE 将此应用于环境中的每个python进程(并取消设置变量以撤消此操作)。
Python 3.3 +
使用python 3.3或更高版本,您只需将
1 | print('foo', flush=True) |
python 2(或<3.3)
它们没有将
1 2 3 4 5 6 7 8 9 10 11 12 | 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() |
上述兼容性代码将涵盖大多数用途,但要进行更彻底的处理,请参阅
或者,您也可以在打印后调用
1 2 3 | import sys print 'delayed output' sys.stdout.flush() |
将一个模块中的默认值更改为
通过在模块的全局范围上使用functools.partial,可以更改打印函数的默认值:
1 2 | import functools print = functools.partial(print, flush=True) |
如果您查看我们的新部分函数,至少在python 3中:
1 2 3 | >>> print = functools.partial(print, flush=True) functools.partial(<built-in function print>, flush=True) |
我们可以看到它像正常一样工作:
1 2 | >>> print('foo') foo |
我们实际上可以覆盖新的默认值:
1 2 | >>> print('foo', flush=False) foo |
请再次注意,这只会更改当前全局范围,因为当前全局范围上的打印名称将覆盖内置的
如果要在函数内部而不是模块的全局范围内执行此操作,则应为其指定一个不同的名称,例如:
1 2 3 | def foo(): printf = functools.partial(print, flush=True) printf('print stuff like this') |
如果您在函数中声明它是全局的,那么您将在模块的全局命名空间中对其进行更改,因此您只需将其放在全局命名空间中,除非具体的行为正是您想要的。
更改进程的默认值我认为这里最好的选择是使用
1 | $ python -u script.py |
或
1 | $ python -um package.module |
来自文档:
Force stdin, stdout and stderr to be totally unbuffered. On systems where it matters, also put stdin, stdout and stderr in binary mode.
Note that there is internal buffering in file.readlines() and File Objects (for line in sys.stdin) which is not influenced by this option. To work around this, you will want to use file.readline() inside a while 1: loop.
更改shell操作环境的默认值
如果将环境变量设置为非空字符串,则可以为环境或从环境继承的环境中的所有Python进程获取此行为:
例如,在Linux或OSX中:
1 | $ export PYTHONUNBUFFERED=TRUE |
或窗口:
1 | C:\SET PYTHONUNBUFFERED=TRUE |
来自文档:
PYTHONUNBUFFERED
If this is set to a non-empty string it is equivalent to specifying the -u option.
补遗
下面是关于python 2.7.12中print函数的帮助-请注意,没有
1 2 3 4 5 6 7 8 9 10 11 | >>> 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. |
另外,如本博客所建议的,可以在无缓冲模式下重新打开
1 | sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) |
之后,每个
使用python 3.x扩展了
1 2 | print(*objects, sep=' ', end=' ', file=sys.stdout, flush=False) |
所以,你可以这样做:
1 | print("Visiting toilet", flush=True) |
python文档条目
使用
1 2 3 4 5 6 7 8 9 10 | 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) |
…现在,您所有的
为什么不尝试使用未缓冲的文件?
1 | f = open('xyz.log', 'a', 0) |
或
1 | sys.stdout = open('out.log', 'a', 0) |
1 2 3 | import sys print 'This will be output immediately.' sys.stdout.flush() |
丹的想法不太管用:
1 2 3 4 5 6 7 8 9 10 11 12 | #!/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" |
结果:
1 2 3 4 | Traceback (most recent call last): File"./passpersist.py", line 12, in <module> print"foo" ValueError: I/O operation on closed file |
我认为问题在于它继承了文件类,实际上这是不必要的。根据sys.stdout的文档:
stdout and stderr needn’t be built-in
file objects: any object is acceptable
as long as it has a write() method
that takes a string argument.
所以改变
1 | class flushfile(file): |
到
1 | class flushfile(object): |
让它工作得很好。
这是我的版本,它也提供了writelines()和fileno():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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做:
1 2 3 4 5 6 7 8 | 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中,可以覆盖打印函数,默认设置为
1 2 3 | def print(*objects, sep=' ', end=' ', file=sys.stdout, flush=True): __builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush) |
我在Python3.4中是这样做的:
1 2 3 | '''To write to screen in real-time''' message = lambda x: print(x, flush=True, end="") message('I am flushing out now...') |