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.

È stato utile?

Soluzione

import sys
sys.stdout.flush()

print per impostazione predefinita stampa su sys.stdout.

Riferimenti

Python 2

Python 3

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 esempio sys.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)

Voce di Python Docs

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...')
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top