How to flush output of print function?

后端 未结 13 1568
旧时难觅i
旧时难觅i 2020-11-21 05:15

How do I force Python\'s print function to output to the screen?

This is not a duplicate of Disable output buffering - the linked question is attempting unbuffe

13条回答
  •  感动是毒
    2020-11-21 05:39

    How to flush output of Python print?

    I suggest five ways of doing this:

    • In Python 3, call print(..., flush=True) (the flush argument is not available in Python 2's print function, and there is no analogue for the print statement).
    • Call file.flush() on the output file (we can wrap python 2's print function to do this), for example, sys.stdout
    • apply this to every print function call in the module with a partial function,
      print = partial(print, flush=True) applied to the module global.
    • apply this to the process with a flag (-u) passed to the interpreter command
    • apply this to every python process in your environment with PYTHONUNBUFFERED=TRUE (and unset the variable to undo this).

    Python 3.3+

    Using Python 3.3 or higher, you can just provide flush=True as a keyword argument to the print function:

    print('foo', flush=True) 
    

    Python 2 (or < 3.3)

    They did not backport the flush argument to Python 2.7 So if you're using Python 2 (or less than 3.3), and want code that's compatible with both 2 and 3, may I suggest the following compatibility code. (Note the __future__ import must be at/very "near the 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()
    

    The above compatibility code will cover most uses, but for a much more thorough treatment, see the six module.

    Alternatively, you can just call file.flush() after printing, for example, with the print statement in Python 2:

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

    Changing the default in one module to flush=True

    You can change the default for the print function by using functools.partial on the global scope of a module:

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

    if you look at our new partial function, at least in Python 3:

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

    We can see it works just like normal:

    >>> print('foo')
    foo
    

    And we can actually override the new default:

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

    Note again, this only changes the current global scope, because the print name on the current global scope will overshadow the builtin print function (or unreference the compatibility function, if using one in Python 2, in that current global scope).

    If you want to do this inside a function instead of on a module's global scope, you should give it a different name, e.g.:

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

    If you declare it a global in a function, you're changing it on the module's global namespace, so you should just put it in the global namespace, unless that specific behavior is exactly what you want.

    Changing the default for the process

    I think the best option here is to use the -u flag to get unbuffered output.

    $ python -u script.py
    

    or

    $ python -um package.module
    

    From the docs:

    Force stdin, stdout and stderr to be totally unbuffered. On systems where it matters, also put stdin, stdout and stderr in binary mode.

    Note that there is internal buffering in file.readlines() and File Objects (for line in sys.stdin) which is not influenced by this option. To work around this, you will want to use file.readline() inside a while 1: loop.

    Changing the default for the shell operating environment

    You can get this behavior for all python processes in the environment or environments that inherit from the environment if you set the environment variable to a nonempty string:

    e.g., in Linux or OSX:

    $ export PYTHONUNBUFFERED=TRUE
    

    or Windows:

    C:\SET PYTHONUNBUFFERED=TRUE
    

    from the docs:

    PYTHONUNBUFFERED

    If this is set to a non-empty string it is equivalent to specifying the -u option.


    Addendum

    Here's the help on the print function from Python 2.7.12 - note that there is no flush argument:

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

提交回复
热议问题