Come svuotare l'output della funzione di stampa?
-
04-07-2019 - |
Domanda
Come posso forzare la funzione di stampa di Python ad essere visualizzata sullo schermo?
Questo non è un duplicato di Disabilita buffering dell'output - la domanda collegata sta tentando senza buffer output, mentre questo è più generale. Le risposte migliori a questa domanda sono troppo potenti o coinvolte per questa (non sono buone risposte per questo), e questa domanda può essere trovata su Google da un neofita relativo.
Soluzione
import sys
sys.stdout.flush()
print
per impostazione predefinita stampa su sys.stdout
.
Riferimenti
Python 2
Python 3
-
flush
-
io.IOBase
- oggetto file - Glossario
- <=> (<=> eredita il metodo <=> da <=>)
Altri suggerimenti
In esecuzione python -h
, vedo un'opzione da riga di comando :
-u: stdout binario senza buffer e stderr; anche PYTHONUNBUFFERED = x vedere la pagina man per i dettagli sul buffering interno relativo a '-u'
Ecco il documento pertinente .
Da Python 3.3, è possibile forzare la normale funzione print()
per svuotare senza la necessità di utilizzare sys.stdout.flush()
; basta impostare il " flush " argomento della parola chiave su true. Da la documentazione :
stampa (* oggetti, sep = '', end = '\ n', file = sys.stdout, flush = False)
Stampa gli oggetti nel file di flusso, separati da sep e seguiti da end. sep, end e file, se presenti, devono essere indicati come argomenti di parole chiave.
Tutti gli argomenti non di parole chiave vengono convertiti in stringhe come str () e scritti nello stream, separati da sep e seguiti da end. Sia sep che end devono essere stringhe; possono anche essere Nessuno, il che significa utilizzare i valori predefiniti. Se non viene fornito alcun oggetto, print () scriverà solo end.
L'argomento file deve essere un oggetto con un metodo write (string); se non è presente o Nessuno, verrà utilizzato sys.stdout. Se l'output è bufferizzato viene solitamente determinato dal file, ma se l'argomento della parola chiave flush è vero, il flusso viene scaricato forzatamente.
Come svuotare l'output della stampa Python?
Suggerisco cinque modi per farlo:
- In Python 3, chiama
print(..., flush=True)
(l'argomento flush non è disponibile nella funzione di stampa di Python 2 e non esiste un analogo per l'istruzione print). - Chiama
file.flush()
sul file di output (per fare ciò possiamo avvolgere la funzione di stampa di python 2), ad esempiosys.stdout
- applicalo a ogni chiamata della funzione di stampa nel modulo con una funzione parziale,
print = partial(print, flush=True)
applicato al modulo globale. - applica questo al processo con un flag (
-u
) passato al comando interprete - applica questo a tutti i processi Python nel tuo ambiente con
PYTHONUNBUFFERED=TRUE
(e disattiva la variabile per annullarlo).
Python 3.3+
Usando Python 3.3 o versioni successive, puoi semplicemente fornire flush=True
come argomento parola chiave alla funzione print
:
print('foo', flush=True)
Python 2 (o < 3.3)
Non hanno eseguito il backport dell'argomento flush
su Python 2.7 Quindi, se si utilizza Python 2 (o meno di 3.3) e si desidera un codice compatibile con 2 e 3, è possibile che suggerisca il seguente codice di compatibilità. (Nota che l'importazione __future__
deve essere in / molto & Quot; vicino al inizio modulo "):
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()
Il codice di compatibilità di cui sopra coprirà la maggior parte degli usi, ma per un trattamento molto più approfondito, vedi il six
modulo .
In alternativa, puoi semplicemente chiamare <=> dopo la stampa, ad esempio, con l'istruzione print in Python 2:
import sys
print 'delayed output'
sys.stdout.flush()
Modifica l'impostazione predefinita in un modulo su <=>
È possibile modificare il valore predefinito per la funzione di stampa utilizzando functools.partial nell'ambito globale di un modulo:
import functools
print = functools.partial(print, flush=True)
se guardi la nostra nuova funzione parziale, almeno in Python 3:
>>> print = functools.partial(print, flush=True)
>>> print
functools.partial(<built-in function print>, flush=True)
Possiamo vedere che funziona come al solito:
>>> print('foo')
foo
E possiamo effettivamente ignorare il nuovo valore predefinito:
>>> print('foo', flush=False)
foo
Nota di nuovo, questo cambia solo l'ambito globale corrente, perché il nome di stampa sull'ambito globale corrente oscurerà la funzione incorporata <=> (o dereferirà la funzione di compatibilità, se usi Python 2, in quell'ambito globale corrente).
Se vuoi farlo all'interno di una funzione anziché nell'ambito globale di un modulo, dovresti dargli un nome diverso, ad es .:
def foo():
printf = functools.partial(print, flush=True)
printf('print stuff like this')
Se lo dichiarate globale in una funzione, lo state cambiando nello spazio dei nomi globale del modulo, quindi dovreste semplicemente inserirlo nello spazio dei nomi globale, a meno che quel comportamento specifico sia esattamente quello che volete.
Modifica del valore predefinito per il processo
Penso che l'opzione migliore qui sia usare il flag <=> per ottenere un output senza buffer.
$ python -u script.py
o
$ python -um package.module
Dai documenti :
Forza lo stdin, lo stdout e lo stderr ad essere totalmente senza buffer. Sui sistemi che contano, metti anche stdin, stdout e stderr in modalità binaria.
Si noti che esiste un buffering interno in file.readlines () e Oggetti file (per la riga in sys.stdin) che non è influenzato da questa opzione. Per ovviare a questo, ti consigliamo di utilizzare file.readline () all'interno di un ciclo while:
Modifica del valore predefinito per l'ambiente operativo della shell
È possibile ottenere questo comportamento per tutti i processi Python nell'ambiente o negli ambienti che ereditano dall'ambiente se si imposta la variabile di ambiente su una stringa non vuota:
ad es. in Linux o OSX:
$ export PYTHONUNBUFFERED=TRUE
o Windows:
C:\SET PYTHONUNBUFFERED=TRUE
dai docs :
PYTHONUNBUFFERED
Se impostato su una stringa non vuota, equivale a specificare l'opzione -u.
annunciodendum
Ecco l'aiuto sulla funzione di stampa da Python 2.7.12 - nota che non esiste no <=> argomento:
>>> 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.
Anche come suggerito in questo blog si può riaprire sys.stdout
in modalità senza buffer:
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
Ogni operazione stdout.write
e print
verrà automaticamente cancellata in seguito.
Con Python 3.x la funzione print()
è stata estesa:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
Quindi, puoi semplicemente fare:
print("Visiting toilet", flush=True)
L'uso dell'opzione -u
della riga di comando funziona, ma è un po 'goffo. Significherebbe che il programma potrebbe comportarsi in modo errato se l'utente invocasse lo script senza l'opzione stdout
. Di solito uso un print
personalizzato, come questo:
class flushfile:
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)
... Ora tutte le tue sys.stdout
chiamate (che usano flush
implicitamente), saranno automaticamente <=> ed.
Perché non provare a utilizzare un file senza buffer?
f = open('xyz.log', 'a', 0)
o
sys.stdout = open('out.log', 'a', 0)
L'idea di Dan non funziona del tutto:
#!/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"
Il risultato:
Traceback (most recent call last):
File "./passpersist.py", line 12, in <module>
print "foo"
ValueError: I/O operation on closed file
Credo che il problema sia che eredita dalla classe del file, che in realtà non è necessario. Secondo i documenti per sys.stdout:
stdout e stderr non devono essere & # 8217; t devono essere integrati oggetti file: qualsiasi oggetto è accettabile purché abbia un metodo write () che accetta un argomento stringa.
cambiando così
class flushfile(file):
a
class flushfile(object):
lo fa funzionare bene.
Ecco la mia versione, che fornisce anche writeelines () e 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()
In Python 3 è possibile sovrascrivere la funzione di stampa con l'impostazione predefinita su flush = True
def print(*objects, sep=' ', end='\n', file=sys.stdout, flush=True):
__builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush)
L'ho fatto in questo modo in Python 3.4:
'''To write to screen in real-time'''
message = lambda x: print(x, flush=True, end="")
message('I am flushing out now...')