Python 禁用输出缓冲

Python 禁用输出缓冲,python,stdout,buffered,Python,Stdout,Buffered,在Python的解释器中,sys.stdout是否默认启用了输出缓冲 如果答案是肯定的,那么禁用它的所有方法是什么 迄今为止的建议: 使用-u命令行开关 将sys.stdout包装在一个对象中,该对象在每次写入后都会刷新 设置pythonunbufferenv变量 sys.stdout=os.fdopen(sys.stdout.fileno(),'w',0) 在执行过程中,是否有其他方法以编程方式在sys/sys.stdout中设置一些全局标志?来自: 您可以跳过整个缓冲区 使用“python-

在Python的解释器中,
sys.stdout
是否默认启用了输出缓冲

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

迄今为止的建议:

  • 使用
    -u
    命令行开关
  • sys.stdout
    包装在一个对象中,该对象在每次写入后都会刷新
  • 设置
    pythonunbuffer
    env变量
  • sys.stdout=os.fdopen(sys.stdout.fileno(),'w',0)
  • 在执行过程中,是否有其他方法以编程方式在
    sys
    /
    sys.stdout
    中设置一些全局标志?

    来自:

    您可以跳过整个缓冲区 使用“python-u”的python进程 (或#!/usr/bin/env python-u等)或 设置环境变量 蟒蛇缓冲

    您还可以将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'
    
    是的

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


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

    是的,默认情况下会启用它。在调用python时,可以使用命令行上的-u选项禁用它。

    获得无缓冲输出的一种方法是使用
    sys.stderr
    而不是
    sys.stdout
    ,或者只需调用
    sys.stdout.flush()
    来显式强制执行写入

    您可以通过执行以下操作轻松重定向打印的所有内容:

    import sys; sys.stdout = sys.stderr
    print "Hello World!"
    
    或仅为特定的
    打印
    语句重定向:

    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)
    import io, os, sys
    try:
        # Python 3, open as binary, then wrap in a TextIOWrapper with write-through.
        sys.stdout = io.TextIOWrapper(open(sys.stdout.fileno(), 'wb', 0), write_through=True)
        # If flushing on newlines is sufficient, as of 3.7 you can instead just call:
        # sys.stdout.reconfigure(line_buffering=True)
    except TypeError:
        # Python 2
        sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
    

    信用证:“Sebastian”,在Python邮件列表的某个地方。

    您还可以使用fcntl更改fly中的文件标志

    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,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
    

    (附加到gc.garbage并不是一个好主意,因为它是放置不可冻结循环的地方,您可能需要检查这些循环。)

    可以正常工作的变体(至少在win32上;python 2.7,ipython 0.12)随后调用(多次):

    def DisOutBuffering():
    如果sys.stdout.name=='':
    sys.stdout=os.fdopen(sys.stdout.fileno(),'w',0)
    如果sys.stderr.name='':
    sys.stderr=os.fdopen(sys.stderr.fileno(),'w',0)
    
    我宁愿把我的答案写进或写进,但因为它们被标记为这一答案的副本(我不同意),我将在这里回答

    由于Python 3.3,print()支持关键字参数“flush”():

    (我发布了一条评论,但不知怎么弄丢了。所以,还是:)

  • 正如我所注意到的,CPython(至少在Linux上)的行为因输出的位置而异。如果它转到tty,则在每个“
    \n”

    如果它进入管道/进程,那么它将被缓冲,您可以使用基于
    flush()
    的解决方案或上面推荐的-u选项

  • 与输出缓冲略微相关:
    如果您使用

    用于系统标准中的行:

  • 然后CPython中的for实现将收集一段时间的输入,然后执行一组输入行的循环体。如果您的脚本即将为每个输入行写入输出,这可能看起来像输出缓冲,但实际上是批处理,因此,
    flush()
    等技术都不会有帮助。 有趣的是,在pypy中没有这种行为。 要避免这种情况,您可以使用

    为True时:
    line=sys.stdin.readline()


    ……

    在Python2.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)
    

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


    stdbuf-oL python

    这与克里斯托夫·苏萨的回答有关,但我还不能发表评论

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

    import functools
    print = functools.partial(print, flush=True)
    
    之后,打印将始终直接刷新输出(除非给出了
    flush=False

    注意,(a)这只回答了部分问题,因为它没有重定向所有输出。但是我想在python中,
    print
    是为
    stdout
    /
    stderr
    创建输出的最常用方法,因此这两行可能涵盖了大多数用例

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


    Python2不提供
    flush
    参数,但您可以模拟此处所述的Python3-type
    print
    函数。

    只可以用调用
    flush
    的方法覆盖
    sys.stdout
    写入方法。建议的方法实现如下

    def write_flush(args, w=stdout.write):
        w(args)
        stdout.flush()
    
    w
    参数的默认值将保留原始的
    write
    方法引用。定义
    write\u flush
    后,可能会覆盖原始的
    write

    stdout.write = write_flush
    

    该代码假定以这种方式从sys import stdout导入
    stdout

    在Python 3中,您可以对print函数进行monkey-patch,以始终发送flush=True:

    _orig_print = print
    
    def print(*args, **kwargs):
        _orig_print(*args, flush=True, **kwargs)
    
    正如注释中指出的,您可以通过
    functools.partial
    将flush参数绑定到一个值来简化此过程:

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

    原来的sys.stdout仍然可以作为sys.\u stdout\uuuu使用。以防万一你需要它=)
    #/usr/bin/env python-u
    不起作用!!为了避免继承,请参见
    \uuuu getattr\uuuu
    ?!我注意到,输出缓冲的工作方式不同
    def write_flush(args, w=stdout.write):
        w(args)
        stdout.flush()
    
    stdout.write = write_flush
    
    _orig_print = print
    
    def print(*args, **kwargs):
        _orig_print(*args, flush=True, **kwargs)
    
    print = functools.partial(print, flush=True)