首页 文章

如何刷新打印功能的输出?

提问于
浏览
939

如何强制Python的打印功能输出到屏幕?

这不是禁用输出缓冲的重复 - 链接的问题是尝试无缓冲输出,而这是更一般的 . 这个问题的最佳答案太强大或涉及到这个问题(他们不是很好的答案),这个问题可以在Google上找到一个相对新手 .

14 回答

  • 264

    同样如this blog中所建议的那样,可以在非缓冲模式下重新打开 sys.stdout

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

    之后将自动刷新每个 stdout.writeprint 操作 .

  • 11

    如何刷新Python打印输出?

    我建议五种方法:

    • 在Python 3中,调用 print(..., flush=True) (在Python 2的print函数中不提供flush参数,并且print语句没有模拟) .

    • 在输出文件上调用 file.flush() (我们可以用python 2的print函数来执行此操作),例如, sys.stdout

    • 将此应用于具有部分功能的模块中的每个打印函数调用,
      print = partial(print, flush=True) 应用于全局模块 .

    • 将此应用程序应用于传递给interpreter命令的标志( -u

    • 将此应用于环境中的每个python进程 PYTHONUNBUFFERED=TRUE (并取消设置该变量以撤消此操作) .

    Python 3.3

    使用Python 3.3或更高版本,您只需提供 flush=True 作为 print 函数的关键字参数:

    print('foo', flush=True)
    

    Python 2(或<3.3)

    他们没有将 flush 参数反向移植到Python 2.7所以如果你're using Python 2 (or less than 3.3), and want code that'兼容2和3,我可以建议以下兼容性代码 . (注意 __future__ 导入必须位于/非常“靠近top of your module”):

    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()
    

    上述兼容性代码将涵盖大多数用途,但对于更彻底的处理,see the six module .

    或者,您可以在打印后调用 file.flush() ,例如,使用Python 2中的print语句:

    import sys
    print 'delayed output'
    sys.stdout.flush()
    

    将一个模块中的默认值更改为flush = True

    您可以在模块的全局范围内使用functools.partial更改打印功能的默认值:

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

    如果你看看我们新的部分函数,至少在Python 3中:

    >>> print = functools.partial(print, flush=True)
    >>> print
    functools.partial(<built-in function print>, flush=True)
    

    我们可以看到它像正常一样工作:

    >>> print('foo')
    foo
    

    我们实际上可以覆盖新的默认值:

    >>> print('foo', flush=False)
    foo
    

    再次注意,这只会更改当前的全局范围,因为当前全局范围上的打印名称将掩盖内置 print 函数(或者取消引用兼容性函数,如果使用Python 2,则在当前的全局范围内) .

    如果你想在一个函数内而不是在一个模块的全局范围内这样做,你应该给它一个不同的名字,例如:

    def foo():
        printf = functools.partial(print, flush=True)
        printf('print stuff like this')
    

    如果在函数中声明它是全局的,那么您将在模块的全局命名空间中更改它,因此您应该将它放在全局命名空间中,除非该特定行为正是您想要的 .

    更改进程的默认值

    我认为这里最好的选择是使用 -u 标志来获得无缓冲的输出 .

    $ python -u script.py
    

    要么

    $ python -um package.module
    

    来自docs

    强制stdin,stdout和stderr完全无缓冲 . 在重要的系统上,还将stdin,stdout和stderr置于二进制模式 . 请注意,file.readlines()和File Objects(对于sys.stdin中的行)中存在内部缓冲,不受此选项的影响 . 要解决此问题,您需要在while 1:循环中使用file.readline() .

    更改shell操作环境的默认值

    如果将环境变量设置为非空字符串,则可以为环境中的所有python进程或从环境继承的环境获取此行为:

    例如,在Linux或OSX中:

    $ export PYTHONUNBUFFERED=TRUE
    

    或Windows:

    C:\SET PYTHONUNBUFFERED=TRUE
    

    来自docs

    PYTHONUNBUFFERED如果将其设置为非空字符串,则相当于指定-u选项 .


    附录

    这是Python 2.7.12中打印函数的帮助 - 请注意,没有 flush 参数:

    >>> from __future__ import print_function
    >>> help(print)
    print(...)
        print(value, ..., sep=' ', end='\n', 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.
    
  • 32
  • 12

    从Python 3.3开始,你可以强制普通的 print() 函数进行刷新而不需要使用 sys.stdout.flush() ;只需将"flush"关键字参数设置为true即可 . 来自the documentation

    print(* objects,sep ='',end ='\ n',file = sys.stdout,flush = False)将对象打印到流文件,用sep分隔,然后用end结束 . sep,end和file(如果存在)必须作为关键字参数给出 . 所有非关键字参数都转换为str()所做的字符串并写入流中,由sep分隔,然后是end . sep和end都必须是字符串;它们也可以是None,这意味着使用默认值 . 如果没有给出对象,print()将只写入结束 . file参数必须是带有write(string)方法的对象;如果它不存在或None,将使用sys.stdout . 输出是否缓冲通常由文件确定,但如果flush关键字参数为true,则强制执行流酡 .

  • 6

    使用Python 3.x, print() 函数已被扩展:

    print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
    

    所以,你可以这样做:

    print("Visiting toilet", flush=True)
    

    Python Docs Entry

  • 65

    我在Python 3.4中这样做了:

    '''To write to screen in real-time'''
    message = lambda x: print(x, flush=True, end="")
    message('I am flushing out now...')
    
  • 17

    使用 -u 命令行开关可以工作,但它有点笨拙 . 这意味着如果用户在没有 -u 选项的情况下调用脚本,程序可能会出现错误行为 . 我通常使用自定义 stdout ,如下所示:

    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)
    

    ...现在所有 print 调用(隐式使用 sys.stdout )将自动 flush 编辑 .

  • 36

    丹的想法并不奏效:

    #!/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"
    

    结果:

    Traceback (most recent call last):
      File "./passpersist.py", line 12, in <module>
        print "foo"
    ValueError: I/O operation on closed file
    

    我相信问题是它继承自文件类,实际上并不是必需的 . 根据sys.stdout的文档:

    stdout和stderr不需要是内置文件对象:任何对象都是可接受的,只要它有一个带有字符串参数的write()方法即可 .

    如此变化

    class flushfile(file):
    

    class flushfile(object):
    

    让它工作得很好 .

  • 1113

    在Python 3中,您可以覆盖打印功能,默认设置为 flush = True

    def print(*objects, sep=' ', end='\n', file=sys.stdout, flush=True):
        __builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush)
    
  • 123

    运行 python -h ,我看到一个命令行选项:

    -u:无缓冲的二进制stdout和stderr;还有PYTHONUNBUFFERED = x有关'-u'内部缓冲的详细信息,请参阅手册页

    这是relevant doc .

  • 2

    为什么不尝试使用无缓冲的文件?

    f = open('xyz.log', 'a', 0)
    

    要么

    sys.stdout = open('out.log', 'a', 0)
    
  • 2
    import sys
    print 'This will be output immediately.'
    sys.stdout.flush()
    
  • 302

    这是我的版本,它也提供了writelines()和fileno():

    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()
    
  • 5

    喜欢Dan的解决方案!对于python3做:

    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)
    

相关问题