Disable output buffering
在python的
如果答案是肯定的,那么禁用它的所有方法是什么?
迄今为止的建议:
在执行过程中,是否有其他方法以编程方式在
从邮件列表上的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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 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'
号
我宁愿把我的答案放在如何刷新python print的输出上?或者在python的print函数中,调用缓冲区时刷新缓冲区?,但是由于它们被标记为这一个的副本(我不同意),我将在这里回答。
因为python 3.3 print()支持关键字参数"flush"(参见文档):
1 | print('Hello World!', flush=True) |
。
1 2 3 | # reopen stdout file descriptor with write mode # and 0 as the buffer size (unbuffered) sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) |
片尾:"塞巴斯蒂安",在python邮件列表的某个地方。
第三方编辑
在最新版本的python 3中不受支持
是的,是的。
您可以使用"-u"开关在命令行上禁用它。
或者,您可以在每次写入时对sys.stdout调用.flush()(或者用自动执行此操作的对象包装它)。
1 2 3 4 5 6 7 8 9 10 11 | 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()不是等幂的,多次调用将导致如下错误:
1 2 3 4 5 | 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 |
另一种可能性是:
1 2 3 4 5 6 7 | 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不是一个好主意,因为它是放置不可冻结循环的地方,您可能需要检查这些循环。)
这与Crist_v有关?O.D.Sousa的回答,但我还不能发表评论。
使用python 3的
1 2 | import functools print = functools.partial(print, flush=True) |
号
之后,打印将始终直接刷新输出(除了提供
注意,(a)这只回答了部分问题,因为它不会重定向所有输出。但是我猜在python中,
注意(b)它只在您定义它的模块/脚本中工作。这在编写模块时是很好的,因为它不会干扰
python 2没有提供
在python 2.6、2.7和3.2中可以使用以下内容:
1 2 3 4 5 6 7 8 | import os import sys buf_arg = 0 if sys.version_info[0] == 3: os.environ['PYTHONUNBUFFERED'] = '1' buf_arg = 1 sys.stdout = os.fdopen(sys.stdout.fileno(), 'a+', buf_arg) sys.stderr = os.fdopen(sys.stderr.fileno(), 'a+', buf_arg) |
号
是,默认情况下启用。调用python时,可以使用命令行上的-u选项来禁用它。
您还可以使用stdbuf工具运行python:
埃多克斯1〔9〕
在不崩溃的情况下工作的变体(至少在win32;python 2.7,ipython 0.12上),然后调用(多次):
1 2 3 4 5 6 | def DisOutBuffering(): if sys.stdout.name == '<stdout>': sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) if sys.stderr.name == '<stderr>': sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0) |
(我贴了一条评论,但不知怎么弄丢了。所以,再一次:)
正如我注意到的,cpython(至少在Linux上)的行为因输出的位置而异。如果它变为tty,则在每个'EDOCX1[4]之后刷新输出。
如果它进入管道/流程,那么它是缓冲的,您可以使用基于
与输出缓冲略有关系:
如果您使用
埃多克斯1〔6〕
…
然后,cpython中的for实现将收集输入一段时间,然后为一组输入行执行循环体。如果您的脚本将要为每个输入行编写输出,这可能看起来像输出缓冲,但实际上是批处理,因此,
埃多克斯1〔8〕
…
只可以用调用
1 2 3 | def write_flush(args, w=stdout.write): w(args) stdout.flush() |
1 | stdout.write = write_flush |
号
该代码假定
您还可以使用fcntl在fly中更改文件标志。
1 2 3 | 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) |
。
您可以创建一个未缓冲的文件,并将该文件分配给sys.stdout。
1 2 3 | import sys myFile= open("a.log","w", 0 ) sys.stdout= myFile |
。
您不能神奇地更改系统提供的stdout;因为它是由操作系统提供给您的python程序的。
在python 3中,可以对print函数进行monkey修补,以始终发送flush=true:
1 2 3 4 | _orig_print = print def print(*args, **kwargs): _orig_print(*args, flush=True, **kwargs) |
获得无缓冲输出的一种方法是使用
您可以通过执行以下操作轻松重定向打印的所有内容:
1 2 | import sys; sys.stdout = sys.stderr print"Hello World!" |
或者仅仅针对特定的
1 | print >>sys.stderr,"Hello World!" |
号
要重置stdout,只需执行以下操作:
1 | sys.stdout = sys.__stdout__ |