Pregunta Cómo vaciar la salida de la función de impresión?


¿Cómo fuerzo la función de impresión de Python para que salga a la pantalla?

Esto no es un duplicado de Desactivar el buffer de salida - la pregunta vinculada está intentando la salida sin búfer, mientras que esto es más general. Las respuestas principales en esa pregunta son demasiado poderosas o involucradas para esta (no son buenas respuestas para esto), y esta pregunta puede ser encontrada en Google por un novato relativo.


886
2017-10-23 17:59


origen


Respuestas:


import sys
sys.stdout.flush()

Imprimir de forma predeterminada imprime en sys.stdout.

Referencias


1049
2017-10-23 18:04



Corriendo python -h, Veo un opción de línea de comando:

-u: stdout y stderr binarios sin búfer; también PYTHONUNBUFFERED = x            consulte la página de manual para obtener detalles sobre el almacenamiento en búfer interno relacionado con '-u'

Aquí está el documento relevante.


292
2017-10-23 18:06



Desde Python 3.3, puedes forzar lo normal print() funcionar para enjuagar sin la necesidad de usar sys.stdout.flush(); simplemente configure el argumento de la palabra clave "flush" como verdadero. De la documentación:

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

Imprima objetos en el archivo de flujo, separados por sep y seguidos por end. sep, end y file, si están presentes, se deben dar como argumentos de palabra clave.

Todos los argumentos que no son palabras clave se convierten en cadenas como str () y se escriben en la secuencia, separadas por sep y seguidas por end. Tanto sep como end deben ser cuerdas; también pueden ser None, lo que significa usar los valores predeterminados. Si no se proporcionan objetos, print () solo escribirá end.

El argumento del archivo debe ser un objeto con un método de escritura (cadena); si no está presente o None, se usará sys.stdout. Si el resultado está almacenado en búfer generalmente se determina por archivo, pero si el argumento de palabra clave de descarga es verdadero, la transmisión se vacía a la fuerza.


244
2018-04-17 20:10



¿Cómo vaciar el resultado de la impresión Python?

Sugiero cinco formas de hacer esto:

  • En Python 3, llame print(..., flush=True) (el argumento de descarga no está disponible en la función de impresión de Python 2, y no hay ningún análogo para la instrucción de impresión).
  • Llamada file.flush() en el archivo de salida (podemos ajustar la función de impresión de Python 2 para hacer esto), por ejemplo, sys.stdout
  • aplicar esto a cada llamada de función de impresión en el módulo con una función parcial,
    print = partial(print, flush=True) aplicado al módulo global.
  • aplicar esto al proceso con una bandera (-u) pasado al comando del intérprete
  • aplicar esto a cada proceso de python en su entorno con PYTHONUNBUFFERED=TRUE (y desarma la variable para deshacer esto).

Python 3.3+

Usando Python 3.3 o superior, solo puede proporcionar flush=True como un argumento de palabra clave para el print función:

print('foo', flush=True) 

Python 2 (o <3.3)

No respaldaron el flush argumento para Python 2.7 Entonces, si está usando Python 2 (o menos de 3.3), y quiere código que sea compatible con ambos, 2 y 3, le sugiero el siguiente código de compatibilidad. (Nota la __future__la importación debe estar en / muy "cerca del parte superior de tu módulo"):

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

El código de compatibilidad anterior cubrirá la mayoría de los usos, pero para un tratamiento mucho más completo, ver el six módulo.

Alternativamente, puedes simplemente llamar file.flush() después de imprimir, por ejemplo, con la declaración de impresión en Python 2:

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

Cambiar el valor predeterminado en un módulo a flush=True

Puede cambiar el valor predeterminado para la función de impresión utilizando functools.partial en el alcance global de un módulo:

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

si nos fijamos en nuestra nueva función parcial, al menos en Python 3:

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

Podemos ver que funciona como siempre:

>>> print('foo')
foo

Y podemos anular el nuevo valor predeterminado:

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

Tenga en cuenta una vez más, esto solo cambia el alcance global actual, ya que el nombre de impresión en el alcance global actual eclipsará el contenido interno actual. print función (o desreferencia la función de compatibilidad, si usa Python 2, en ese alcance global actual).

Si desea hacer esto dentro de una función en lugar de en el ámbito global de un módulo, debe darle un nombre diferente, por ejemplo:

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

Si declara que es global en una función, la está cambiando en el espacio de nombres global del módulo, por lo que debe colocarlo en el espacio de nombres global, a menos que ese comportamiento específico sea exactamente lo que desea.

Cambiar el valor predeterminado para el proceso

Creo que la mejor opción aquí es usar el -u bandera para obtener salida sin búfer.

$ python -u script.py

o

$ python -um package.module

Desde el documentos:

Fuerza stdin, stdout y stderr para ser totalmente sin buffer. En sistemas donde es importante, también coloque stdin, stdout y stderr en modo binario.

Tenga en cuenta que hay un búfer interno en file.readlines () y File Objects (para la línea en sys.stdin) que no está influenciado por esta opción. Para solucionar esto, querrás usar file.readline () dentro de un while 1: loop.

Cambiar el valor predeterminado para el entorno operativo del shell

Puede obtener este comportamiento para todos los procesos de python en el entorno o entornos que hereden del entorno si establece la variable de entorno en una cadena no vacía:

por ejemplo, en Linux o OSX:

$ export PYTHONUNBUFFERED=TRUE

o Windows:

C:\SET PYTHONUNBUFFERED=TRUE

desde el documentos:

PYTHONUNBUFFERED

Si se establece en una cadena no vacía, equivale a especificar la opción -u.


Apéndice

Aquí está la ayuda sobre la función de impresión de Python 2.7.12: tenga en cuenta que hay no  flush argumento:

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

100
2018-02-17 21:01



También como se sugiere en este blog uno puede reabrir sys.stdout en modo sin búfer:

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

Cada stdout.write y print la operación se purgará automáticamente después.


65
2018-02-27 08:38



Utilizando el -u El interruptor de línea de comandos funciona, pero es un poco torpe. Significaría que el programa se comportaría potencialmente incorrectamente si el usuario invoca el script sin el -u opción. Usualmente uso una costumbre stdout, Me gusta esto:

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)

... Ahora todo tu print llamadas (que usan sys.stdout implícitamente), será automáticamente flushed.


30
2017-10-23 19:54



Con Python 3.x extendieron la print()función:

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

Entonces, puedes hacer lo siguiente:

print("Visiting toilet", flush=True)

Entrada de Python Docs


22
2017-10-21 17:23



¿Por qué no intentar usar un archivo sin búfer?

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

O

sys.stdout = open('out.log', 'a', 0)

17
2018-04-12 10:57



import sys
print 'This will be output immediately.'
sys.stdout.flush()

12
2017-12-12 07:46



La idea de Dan no funciona:

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

El resultado:

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

Creo que el problema es que hereda de la clase de archivo, que en realidad no es necesaria. De acuerdo con los documentos para sys.stdout:

stdout y stderr no necesitan ser incorporados   objetos de archivo: cualquier objeto es aceptable   siempre que tenga un método write ()   eso toma un argumento de cadena.

tan cambiante

class flushfile(file):

a

class flushfile(object):

lo hace funcionar bien.


10
2017-11-13 22:15



Aquí está mi versión, que también proporciona writelines () y 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()

6
2018-05-19 08:20