禁用输出缓冲
时间:2020-03-06 14:28:51 来源:igfitidea点击:
默认情况下,Python的sys.stdout解释器是否启用了输出缓冲?
如果答案是肯定的,那么有什么方法可以禁用它?
到目前为止的建议:
- 使用-u命令行开关
- 在每次写入后刷新的对象中包装sys.stdout
- 设置
PYTHONUNBUFFERED
env var - sys.stdout = os.fdopen(sys.stdout.fileno(),'w',0)`
还有其他方法可以在执行过程中以编程方式在sys / sys.stdout中设置一些全局标志吗?
解决方案
从Magnus Lycka的邮件列表中答复:
You can skip buffering for a whole python process using "python -u" (or#!/usr/bin/env python -u etc) or by setting the environment variable PYTHONUNBUFFERED. You could also replace sys.stdout with some other stream like wrapper which does a flush after every call. class Unbuffered(object): def __init__(self, stream): self.stream = stream def write(self, data): self.stream.write(data) self.stream.flush() def writelines(self, datas): self.stream.writelines(datas) self.stream.flush() def __getattr__(self, attr): return getattr(self.stream, attr) import sys sys.stdout = Unbuffered(sys.stdout) print 'Hello'
是的。
我们可以使用" -u"开关在命令行上禁用它。
或者,我们可以在每次写入时在sys.stdout上调用.flush()(或者将其包装为自动执行此操作的对象)
是的,默认情况下启用。我们可以在调用python时通过在命令行上使用-u选项禁用它。
获得无缓冲输出的一种方法是使用sys.stderr而不是sys.stdout或者简单地调用sys.stdout.flush()显式强制进行写操作。
我们可以通过执行以下操作轻松重定向所有打印内容:
import sys; sys.stdout = sys.stderr print "Hello World!"
或者仅针对特定的print
语句进行重定向:
print >>sys.stderr, "Hello World!"
要重置标准输出,我们可以执行以下操作:
sys.stdout = sys.__stdout__
我们可以创建一个无缓冲的文件,并将该文件分配给sys.stdout。
import sys myFile= open( "a.log", "w", 0 ) sys.stdout= myFile
我们无法神奇地更改系统提供的标准输出;因为它是由操作系统提供给python程序的。
# reopen stdout file descriptor with write mode # and 0 as the buffer size (unbuffered) sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
鸣谢:" Sebastian",在Python邮件列表上的某处。
我们还可以使用fcntl即时更改文件标志。
fl = fcntl.fcntl(fd.fileno(), fcntl.F_GETFL) fl |= os.O_SYNC # or os.O_DSYNC (if you don't care the file timestamp updates) fcntl.fcntl(fd.fileno(), fcntl.F_SETFL, fl)
def disable_stdout_buffering(): # Appending to gc.garbage is a way to stop an object from being # destroyed. If the old sys.stdout is ever collected, it will # close() stdout, which is not good. gc.garbage.append(sys.stdout) sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) # Then this will give output in the correct order: disable_stdout_buffering() print "hello" subprocess.call(["echo", "bye"])
如果不保存旧的sys.stdout,disable_stdout_buffering()并不是幂等的,并且多次调用将导致如下错误:
Traceback (most recent call last): File "test/buffering.py", line 17, in <module> print "hello" IOError: [Errno 9] Bad file descriptor close failed: [Errno 9] Bad file descriptor
另一种可能性是:
def disable_stdout_buffering(): fileno = sys.stdout.fileno() temp_fd = os.dup(fileno) sys.stdout.close() os.dup2(temp_fd, fileno) os.close(temp_fd) sys.stdout = os.fdopen(fileno, "w", 0)
(添加到gc.garbage并不是一个好主意,因为这是放置不可释放的循环的地方,我们可能需要检查这些循环。)