当前位置:  开发笔记 > 编程语言 > 正文

禁用输出缓冲

如何解决《禁用输出缓冲》经验,为你挑选了10个好方法。

Python的解释器默认启用输出缓冲sys.stdout吗?

如果答案是肯定的,那么禁用它的所有方法是什么?

建议到目前为止:

    使用-u命令行开关

    包装sys.stdout在每次写入后刷新的对象

    设置PYTHONUNBUFFEREDenv var

    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

是否有任何其他方式来设置一些全局标志sys/ sys.stdout程序执行过程中?



1> Seb..:

来自Magnus Lycka的回复邮件列表:

您可以使用"python -u"(或#!/ usr/bin/env python -u等)或通过设置环境变量PYTHONUNBUFFERED来跳过整个python进程的缓冲.

您还可以将sys.stdout替换为其他流,例如在每次调用后执行刷新的包装器.

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'


原始sys.stdout仍可用作sys .__ stdout__.万一你需要它=)
`#!/ usr/bin/env python -u`不起作用!! 见[这里](http://stackoverflow.com/q/3306518/674039)
保存一些令人头疼的注意事项:正如我所注意到的,输出缓冲的工作方式不同,具体取决于输出是转到tty还是其他进程/管道.如果它转到tty,则在每个*\n*之后刷新,但在管道中它被缓冲.在后一种情况下,您可以使用这些冲洗解决方案.在Cpython中(不是pypy !!!):如果你在sys.stdin中使用**替换输入:**...那么for循环将在循环体运行之前收集许多行.这将表现得像缓冲,虽然它是相当批处理.相反,执行**而true:line = sys.stdin.readline()**
`__getattr__`只是为了避免继承?!
@tzp:你可以使用`iter()`而不是`while`循环:`for iter in iter(pipe.readline,''):`.在Python 3中你不需要它,其中`for line in pipe:`尽快产生.
@tzp:当使用`python myscript.py |时,这种不同的行为特别令人生气。tee logfile.txt`-目的是在记录日志的同时查看您的操作!

2> Cristóvão D...:

我宁愿把答案放在如何刷新Python打印输出?或者在Python的print函数中,在调用缓冲区时刷新缓冲区?,但由于它们被标记为这个副本(我不同意),我会在这里回答.

由于Python 3.3 print()支持关键字参数"flush"(参见文档):

print('Hello World!', flush=True)



3> Federico A. ..:
# reopen stdout file descriptor with write mode
# and 0 as the buffer size (unbuffered)
import io, os, sys
try:
    # Python 3, open as binary, then wrap in a TextIOWrapper, and write through
    # everything. Alternatively, use line_buffering=True to flush on newlines.
    unbuffered = io.TextIOWrapper(open(sys.stdout.fileno(), 'wb', 0), write_through=True)
except TypeError:
    # Python 2
    unbuffered = os.fdopen(sys.stdout.fileno(), 'w', 0)

致谢:"塞巴斯蒂安",在Python邮件列表的某个地方.

第三方编辑

最新版本的Python 3不支持


@meawoppl:你可以从Python 3.3开始将`ftush = True`参数传递给`print()`函数.

4> Brian..:

是的.

您可以使用"-u"开关在命令行上禁用它.

或者,您可以在每次写入时在sys.stdout上调用.flush()(或者使用自动执行此操作的对象将其包装)



5> tim..:

这与CristóvãoD.Sousa的答案有关,但我还没有发表评论.

使用Python 3flush关键字参数以便始终具有无缓冲输出的直接方式是:

import functools
print = functools.partial(print, flush=True)

之后,print将始终直接刷新输出(除非flush=False给出).

注意,(a)这只是部分回答了问题,因为它没有重定向所有输出.不过,我想print是一个用于创建输出的最常用的方法stdout/ stderrPython中,所以这两条线可能覆盖大部分的用例.

注意(b)它只适用于您定义它的模块/脚本.这在编写模块时可能很好,因为它不会弄乱模块sys.stdout.

Python 2不提供flush参数,但您可以模拟Python 3类型的print函数,如/sf/ask/17360801/所述.



6> Mark Seaborn..:
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 
    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并不是一个好主意,因为它是放置不合理周期的地方,你可能想要检查那些.)


如果旧的`stdout`仍然存在于某些人所建议的`sys .__ stdout__`中,那么垃圾就没有必要了,对吧?这是一个很酷的技巧.

7> Nathan..:

是的,它默认启用.您可以在调用python时在命令行上使用-u选项禁用它.



8> 小智..:

以下适用于Python 2.6,2.7和3.2:

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)



9> dyomas..:

您还可以使用stdbuf实用程序运行Python :

stdbuf -oL python

kikokikolove
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有