La differenza tra sys.stdout.write e stampa?


376

Ci sono situazioni in cui sys.stdout.write()è preferibile print?

( Esempi: prestazioni migliori; codice che ha più senso)


4
Quale versione di Python? 2.xo 3.x?
Mark Byers,

Sinceramente mi piacerebbe saperlo per entrambi, anche se non ho esperienza con Python 3. Aggiornato la domanda.
Johanna Larsson,

17
@ S.Lott: chiedere le differenze di base tra sys.stdout.write()e print(e / o perché Python ha entrambe) è una domanda perfettamente ragionevole e non ha bisogno di esempi. OP non ha detto che la sintassi del comando era confusa.
smci,

Risposte:


294

printè solo un wrapper sottile che formatta gli input (modificabili, ma per impostazione predefinita con uno spazio tra args e newline alla fine) e chiama la funzione di scrittura di un determinato oggetto. Per impostazione predefinita, questo oggetto è sys.stdout, ma è possibile passare un file utilizzando il modulo "chevron". Per esempio:

print >> open('file.txt', 'w'), 'Hello', 'World', 2+3

Vedi: https://docs.python.org/2/reference/simple_stmts.html?highlight=print#the-print-statement


In Python 3.x printdiventa una funzione, ma è ancora possibile passare qualcosa di diverso da quello sys.stdoutgrazie fileall'argomento.

print('Hello', 'World', 2+3, file=open('file.txt', 'w'))

Vedi https://docs.python.org/3/library/functions.html#print


In Python 2.6+, printè ancora un'istruzione, ma può essere utilizzata come funzione con

from __future__ import print_function

Aggiornamento: Bakuriu ha commentato per sottolineare che c'è una piccola differenza tra la funzione di stampa e l'istruzione di stampa (e più in generale tra una funzione e un'istruzione).

In caso di errore durante la valutazione degli argomenti:

print "something", 1/0, "other" #prints only something because 1/0 raise an Exception

print("something", 1/0, "other") #doesn't print anything. The function is not called

64
Vale anche la pena notare che printaggiunge anche una nuova riga a tutto ciò che scrivi con cui non accade sys.stdout.write.
Michael Mior,

5
Inoltre sys.stdout.writeè più universale se hai mai bisogno di scrivere codice a doppia versione (ad esempio codice che funziona contemporaneamente con Python 2.xe Python 3.x).
andreb,

3
@MichaelMior Puoi sopprimere la nuova riga che si printaggiunge con una virgola finale:print "this",; print "on the same line as this"
drevicko

1
@ bjd2385 Qui >>non è l'operatore rshift ma una forma "chevron" specifica dell'istruzione print. Vedi docs.python.org/2/reference/…
luc

5
sys.stdout.write()buffer anche l'input e potrebbe non inviare immediatamente l'input a fd. per assicurarti che si comporti come la funzione di stampa, devi aggiungere: sys.stdout.flush()
kerbelp

151

printprima converte l'oggetto in una stringa (se non è già una stringa). Metterà anche uno spazio prima dell'oggetto se non è l'inizio di una linea e un carattere di nuova riga alla fine.

Quando si utilizza stdout, è necessario convertire l'oggetto in una stringa da soli (chiamando ad esempio "str") e non esiste un carattere di nuova riga.

Così

print 99

è equivalente a:

import sys
sys.stdout.write(str(99) + '\n')

32
+1 per menzionare il personaggio newline! Questa è la differenza principale tra printe .write(), direi.
Eric O Lebigot,

9
NOTA: printpuò essere fatto per omettere la nuova riga. In Python 2.x, inserisci una virgola alla fine e verrà emesso un carattere spazio, ma nessuna nuova riga. Ad esempio, print 99,in Python 3, print(..., end='')eviterai di aggiungere newline (ed eviterai anche di aggiungere spazio, a meno che tu non lo faccia end=' '.
ToolmakerSteve

40
@EOL Com'è divertente che qualcuno di nome EOL faccia un commento su '\ n' ... Mi ha fatto ridere. Non ho una vita. Uccidimi.
Depado,

2
Non è vero, printsi comporta di funzionamento leggermente diverse in gestori di segnale in python2.X, vale a dire di stampa non possono essere sostituiti con sys.stdout nell'esempio: stackoverflow.com/questions/10777610/...
ddzialak

41

La mia domanda è se ci sono situazioni in cui sys.stdout.write()è preferibile o meno print

Dopo aver finito di sviluppare uno script l'altro giorno, l'ho caricato su un server unix. Tutti i miei messaggi di debug utilizzavano printistruzioni e queste non compaiono nel registro del server.

Questo è un caso in cui potrebbe essere necessario sys.stdout.writeinvece.


8
eh? Sei sicuro che questa sia una differenza tra print()e sys.stdout.write(), al contrario della differenza tra stdoute stderr? Per il debug, è necessario utilizzare il loggingmodulo, sul quale vengono stampati i messaggi stderr.
ostrokach,

1
Ya. Lo stesso vale per l'utilizzo nohupe il reindirizzamento a un .outfile.
conner.xyz,

1
l'uso di sys.stdout.flush () sarebbe di aiuto.
Supporta Chaudhary il

Se si utilizza nohup, per impostazione predefinita tutte le operazioni di scrittura su stdoute stderrverranno reindirizzate nohup.out, indipendentemente dal fatto che si usi printo stdout.write.
Zheng Liu,

40

Ecco un esempio di codice basato sul libro Learning Python di Mark Lutz che risponde alla tua domanda:

import sys
temp = sys.stdout                 # store original stdout object for later
sys.stdout = open('log.txt', 'w') # redirect all prints to this log file
print("testing123")               # nothing appears at interactive prompt
print("another line")             # again nothing appears. it's written to log file instead
sys.stdout.close()                # ordinary file object
sys.stdout = temp                 # restore print commands to interactive prompt
print("back to normal")           # this shows up in the interactive prompt

L'apertura di log.txt in un editor di testo rivelerà quanto segue:

testing123
another line

Esiste un modo per poter stampare sullo schermo e scrivere sul file?
Devesh Saini,

5
@DeveshSaini: Sì, basta sovrascrivere sys.stdout con una classe proxy che abbia almeno una funzione write () e flush (). Ho scritto un frammento di esempio qui .
ponycat,

14

C'è almeno una situazione in cui vuoi sys.stdoutinvece di stampare.

Quando si desidera sovrascrivere una linea senza passare alla riga successiva, ad esempio mentre si disegna una barra di avanzamento o un messaggio di stato , è necessario passare in rassegna qualcosa come

Note carriage return-> "\rMy Status Message: %s" % progress

E poiché la stampa aggiunge una nuova riga, è meglio usare sys.stdout.


2
Se print aggiunge una nuova riga, perché non stampare invece ('message', end = '')?
Apoorv Patne,

8

La mia domanda è se ci sono situazioni in cui sys.stdout.write()è preferibile o menoprint

Se stai scrivendo un'applicazione da riga di comando che può scrivere sia su file che su stdout, è utile. Puoi fare cose come:

def myfunc(outfile=None):
    if outfile is None:
        out = sys.stdout
    else:
        out = open(outfile, 'w')
    try:
        # do some stuff
        out.write(mytext + '\n')
        # ...
    finally:
        if outfile is not None:
            out.close()

Significa che non puoi usare il with open(outfile, 'w') as out:modello, ma a volte ne vale la pena.


A rigor di termini, è possibile utilizzare with- def process(output): # .../ if outfile is None: process(sys.stdout) else: with open(outfile, 'w') as out: process(out)(aggiungendo nuove righe, se necessario, ovviamente). Non è sicuramente molto pulito, però, questo è certo.
Finanzia la causa di Monica il

4

In 2.x, l' printistruzione preelabora ciò che gli dai, trasformandolo in stringhe lungo il percorso, gestendo separatori e newline e consentendo il reindirizzamento a un file. 3.x lo trasforma in una funzione, ma ha ancora le stesse responsabilità.

sys.stdout è un file o simile a un file che ha metodi per scrivere su di esso che prendono stringhe o qualcosa del genere.


3

è preferibile quando la stampa dinamica è utile, ad esempio, per fornire informazioni in un lungo processo:

import time, sys
Iterations = 555
for k in range(Iterations+1):
    # some code to execute here ...
    percentage = k / Iterations
    time_msg = "\rRunning Progress at {0:.2%} ".format(percentage)
    sys.stdout.write(time_msg)
    sys.stdout.flush()
    time.sleep(0.01)

2
print (time_msg, end = '') invece sys.stdout.write (time_msg) sys.stdout.flush () funziona anche
rluts,

2
>>> sys.stdout.write(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected a string or other character buffer object
>>> sys.stdout.write("a")
a>>> sys.stdout.write("a") ; print(1)
a1

Osservando l'esempio sopra:

  1. sys.stdout.writenon scriverà oggetto non stringa, ma lo printfarà

  2. sys.stdout.writenon aggiungerà un nuovo simbolo di linea alla fine, ma lo printfarà

Se ci immergiamo profondamente,

sys.stdout è un oggetto file che può essere utilizzato per l'output di print ()

se l'argomento file di print()non è specificato, sys.stdoutverrà utilizzato


1

Ci sono situazioni in cui è preferibile stampare sys.stdout.write ()?

Ad esempio, sto lavorando a una piccola funzione che stampa le stelle in formato piramidale dopo aver passato il numero come argomento, anche se puoi farlo usando end = "" per stampare in una riga separata, ho usato sys.stdout.write in coordinazione con stampa per farlo funzionare. Per elaborare questo stdout.write stampa nella stessa riga dove stampa stampa sempre il suo contenuto in una riga separata.

import sys

def printstars(count):

    if count >= 1:
        i = 1
        while (i <= count):
            x=0
            while(x<i):
                sys.stdout.write('*')
                x = x+1
            print('')
            i=i+1

printstars(5)

1

Ci sono situazioni in cui è preferibile stampare sys.stdout.write ()?

Ho scoperto che stdout funziona meglio della stampa in una situazione di multithreading. Uso la coda (FIFO) per memorizzare le linee da stampare e tengo tutti i fili prima della linea di stampa fino a quando la mia Q di stampa è vuota. Anche così, usando print a volte perdo il \ n finale sull'I / O di debug (usando l'IDE pro dell'ala).

Quando uso std.out con \ n nella stringa, i formati di I / O di debug correttamente e gli \ n vengono visualizzati con precisione.


Sai qualche motivo per cui stdout dovrebbe funzionare meglio della stampa in questo caso o è aneddotico? Potresti fornire un esempio minimo di lavoro in cui ciò accade?
user2653663

Penso che stdout funzioni a un livello inferiore rispetto alla stampa. Ho sicuramente avuto la corruzione del thread mentre due routine di stampa stavano lottando per sfamare stdout. Scrivere a stdout uno da ogni thread ha rimosso la corruzione per me.
David Poundall,


1

In Python 3 c'è un motivo valido per usare la stampa sys.stdout.write, ma questo motivo può anche essere trasformato in un motivo da usare sys.stdout.write.

Questo è il motivo per cui, ora la stampa è una funzione in Python 3, puoi sovrascriverla. Quindi puoi usare print ovunque in un semplice script e decidere stderrinvece di scrivere quelle dichiarazioni di stampa . Ora puoi semplicemente ridefinire la funzione di stampa, puoi persino cambiare la funzione di stampa globale cambiandola usando il modulo incorporato. Ovviamente file.writepuoi specificare quale file è, ma con la sovrascrittura di stampa puoi anche ridefinire il separatore di riga o il separatore di argomenti.

Il contrario è. Forse sei assolutamente certo di scrivere stdout, ma sai anche che cambierai la stampa in qualcos'altro, puoi decidere di usare sys.stdout.writee usare print per il registro errori o qualcos'altro.

Quindi, ciò che usi dipende da come intendi utilizzarlo. printè più flessibile, ma può essere un motivo per usarlo e non usarlo. Preferirei comunque optare per la flessibilità e scegliere la stampa. Un altro motivo da usare printinvece è la familiarità. Più persone ora capiranno cosa intendi per stampa e meno lo sapranno sys.stdout.write.


1

Una delle differenze è la seguente, quando si tenta di stampare un byte nel suo aspetto esadecimale. Ad esempio, sappiamo che il valore decimale 255è 0xFFin apparenza esadecimale:

val = '{:02x}'.format(255) 

sys.stdout.write(val) # prints ff2
print(val)            # prints ff

Non è di questo che si tratta. Succederebbe solo in una shell interattiva e perché ... write()non ha aggiunto \ne restituisce (e visualizza la shell interattiva) il valore di ritorno della funzione (numero di caratteri scritti), la rappresentazione esadecimale o qualsiasi altro contenuto visualizzato è irrilevante.
Ondrej K.

0

In python 2 se devi passare intorno a una funzione, puoi assegnare os.sys.stdout.write a una variabile, non puoi farlo (nella sostituzione) con print.

>import os
>>> cmd=os.sys.stdout.write
>>> cmd('hello')
hello>>> 

Funziona come previsto.

>>> cmd=print
  File "<stdin>", line 1
    cmd=print
            ^
SyntaxError: invalid syntax

Questo non funziona la stampa è una funzione magica.


0

Una differenza tra printe sys.stdout.writeda sottolineare in Python 3, è anche il valore che viene restituito quando eseguito nel terminale. In Python 3 sys.stdout.writerestituisce la lunghezza della stringa mentre printrestituisce semplicemente None.

Quindi, ad esempio, l'esecuzione in modo interattivo del codice seguente nel terminale stamperebbe la stringa seguita dalla sua lunghezza, poiché la lunghezza viene restituita ed emessa quando viene eseguita in modo interattivo:

>>> sys.stdout.write(" hi ")
 hi 4
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.