Der Unterschied zwischen sys.stdout.write und print?


376

Gibt es Situationen, in denen dies sys.stdout.write()vorzuziehen ist print?

( Beispiele: bessere Leistung; sinnvollerer Code)


4
Welche Version von Python? 2.x oder 3.x?
Mark Byers

Ehrlich gesagt würde ich gerne für beide wissen, obwohl ich keine Erfahrung mit Python 3 habe. Die Frage wurde aktualisiert.
Johanna Larsson

17
@ S.Lott: Nach den grundlegenden Unterschieden zwischen sys.stdout.write()und zu fragen print(und / oder warum Python beides hat) ist eine völlig vernünftige Frage und benötigt keine Beispiele. OP sagte nicht, dass die Befehlssyntax verwirrend sei.
smci

Antworten:


294

printist nur ein dünner Wrapper, der die Eingaben formatiert (modifizierbar, aber standardmäßig mit einem Leerzeichen zwischen args und newline am Ende) und die Schreibfunktion eines bestimmten Objekts aufruft. Standardmäßig ist dieses Objekt sys.stdout, aber Sie können eine Datei mit dem Formular "Chevron" übergeben. Zum Beispiel:

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

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


In Python 3.x printwird eine Funktion, aber es ist immer noch möglich, etwas anderes als sys.stdoutdank des fileArguments zu übergeben.

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

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


In Python 2.6+ printist es immer noch eine Anweisung, aber es kann als Funktion mit verwendet werden

from __future__ import print_function

Update: Bakuriu kommentierte, um darauf hinzuweisen, dass es einen kleinen Unterschied zwischen der Druckfunktion und der Druckanweisung gibt (und allgemeiner zwischen einer Funktion und einer Anweisung).

Im Falle eines Fehlers bei der Bewertung der Argumente:

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
Es ist auch erwähnenswert, dass printauch eine neue Zeile an alles angehängt wird, was Sie schreiben, was nicht passiert sys.stdout.write.
Michael Mior

5
Auch sys.stdout.writeist universeller , wenn Sie jemals Dual-Version Code (zB Code, der gleichzeitig mit Python 2.x sowie Python 3.x funktioniert) schreiben müssen.
Andre

3
@ MichaelMior Sie können die neue printZeile, die mit einem nachgestellten Komma angehängt wird, unterdrücken:print "this",; print "on the same line as this"
Drevicko

1
@ bjd2385 Das >>ist hier nicht der rshift-Operator, sondern eine bestimmte "Chevron" -Form der printAnweisung. Siehe docs.python.org/2/reference/…
luc

5
sys.stdout.write()puffert auch die Eingabe und spült die Eingabe möglicherweise nicht sofort auf den fd. Um sicherzustellen, dass es sich wie die Druckfunktion verhält, sollten Sie hinzufügen: sys.stdout.flush()
Kerbelp

151

printkonvertiert zuerst das Objekt in eine Zeichenfolge (falls es noch keine Zeichenfolge ist). Es wird auch ein Leerzeichen vor dem Objekt eingefügt, wenn es nicht der Anfang einer Zeile und ein Zeilenumbruchzeichen am Ende ist.

Bei der Verwendung stdoutmüssen Sie das Objekt selbst in eine Zeichenfolge konvertieren (z. B. durch Aufrufen von "str"), und es gibt kein Zeilenumbruchzeichen.

Damit

print 99

ist äquivalent zu:

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

32
+1 für die Erwähnung des Zeilenumbruchs! Dies ist der Hauptunterschied zwischen printund .write(), würde ich sagen.
Eric O Lebigot

9
HINWEIS: printkann gemacht werden, um die neue Zeile wegzulassen. Setzen Sie in Python 2.x ein Komma am Ende, und ein Leerzeichen wird ausgegeben, aber keine neue Zeile. ZB wird print 99,in Python 3 print(..., end='')das Hinzufügen von Zeilenumbrüchen vermieden (und auch das Hinzufügen von Speicherplatz, sofern Sie dies nicht tun end=' '.
ToolmakerSteve

40
@EOL Wie lustig ist das, dass jemand namens EOL einen Kommentar zu '\ n' macht ... Es hat mich zum Lachen gebracht. Ich habe kein Leben. Töte mich.
Depado

2
das ist NICHT wahr, die printOperation verhält sich in Signalhandlern in python2.X etwas anders, dh print kann nicht durch sys.stdout ersetzt werden, zum Beispiel: stackoverflow.com/questions/10777610/…
ddzialak

41

Meine Frage ist, ob es Situationen gibt, in denen dies sys.stdout.write()vorzuziehen ist print

Nachdem ich neulich ein Skript entwickelt hatte, habe ich es auf einen Unix-Server hochgeladen. Alle meine Debug-Meldungen verwendeten printAnweisungen, und diese werden nicht in einem Serverprotokoll angezeigt.

Dies ist ein Fall, in dem Sie möglicherweise sys.stdout.writestattdessen benötigen .


8
huh? Sind Sie sicher, dass dies ein Unterschied zwischen print()und ist sys.stdout.write(), im Gegensatz zu dem Unterschied zwischen stdoutund stderr? Zum Debuggen sollten Sie das loggingModul verwenden, an das Nachrichten gedruckt werden stderr.
Ostrokach

1
Ja. Gleiches gilt für die Verwendung nohupund Umleitung in eine .outDatei.
conner.xyz

1
Die Verwendung von sys.stdout.flush () würde helfen.
Suprit Chaudhary

Wenn Sie verwenden nohup, werden standardmäßig alle Schreibvorgänge an stdoutund stderrwerden an diese weitergeleitet nohup.out, unabhängig davon, ob Sie printoder verwenden stdout.write.
Zheng Liu

40

Hier ist ein Beispielcode basierend auf dem Buch Learning Python von Mark Lutz, der Ihre Frage beantwortet:

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

Wenn Sie log.txt in einem Texteditor öffnen, wird Folgendes angezeigt:

testing123
another line

Gibt es eine Möglichkeit, auf dem Bildschirm zu drucken und in die Datei zu schreiben?
Devesh Saini

5
@DeveshSaini: Ja, überschreiben Sie einfach sys.stdout mit einer Proxy-Klasse, die mindestens die Funktionen write () und flush () hat. Ich schrieb ein Beispiel Schnipsel hier .
Ponycat

14

Es gibt mindestens eine Situation, in der Sie sys.stdoutanstelle von Drucken möchten .

Wenn Sie eine Zeile überschreiben möchten, ohne zur nächsten Zeile zu wechseln, z. B. beim Zeichnen eines Fortschrittsbalkens oder einer Statusmeldung , müssen Sie eine Schleife über eine solche Zeile ausführen

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

Und da beim Drucken eine neue Zeile hinzugefügt wird, sollten Sie diese besser verwenden sys.stdout.


2
Wenn print eine neue Zeile hinzufügt, warum nicht einfach drucken ('message', end = '')?
Apoorv Patne

8

Meine Frage ist, ob es Situationen gibt, in denen dies sys.stdout.write()vorzuziehen istprint

Wenn Sie eine Befehlszeilenanwendung schreiben, die sowohl in Dateien als auch in stdout schreiben kann, ist dies praktisch. Sie können Dinge tun wie:

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

Es bedeutet, dass Sie das with open(outfile, 'w') as out:Muster nicht verwenden können , aber manchmal lohnt es sich.


Streng genommen, Sie können verwenden with- def process(output): # .../ if outfile is None: process(sys.stdout) else: with open(outfile, 'w') as out: process(out)(Hinzufügen von Zeilenumbrüchen bei Bedarf natürlich). Es ist definitiv nicht sehr sauber, das ist sicher.
Fund Monica Klage

4

In 2.x verarbeitet die printAnweisung das, was Sie ihr geben, vor, wandelt es auf dem Weg in Zeichenfolgen um, behandelt Trennzeichen und Zeilenumbrüche und ermöglicht die Umleitung in eine Datei. 3.x verwandelt es in eine Funktion, hat aber immer noch die gleichen Verantwortlichkeiten.

sys.stdout ist eine Datei oder eine Datei, die Methoden zum Schreiben enthält, die Zeichenfolgen oder ähnliches in dieser Richtung enthalten.


3

Es ist vorzuziehen, wenn dynamisches Drucken nützlich ist, um beispielsweise Informationen in einem langen Prozess bereitzustellen:

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 = '') statt sys.stdout.write (time_msg) sys.stdout.flush () funktioniert auch
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

Beachten Sie das obige Beispiel:

  1. sys.stdout.writenicht Nicht-String - Objekt, schreiben , sondern printwird

  2. sys.stdout.writekein neues Liniensymbol am Ende, fügt aber printwird

Wenn wir tief tauchen,

sys.stdout ist ein Dateiobjekt, das für die Ausgabe von print () verwendet werden kann.

Wenn das Dateiargument von print()nicht angegeben ist, sys.stdoutwird es verwendet


1

Gibt es Situationen, in denen sys.stdout.write () dem Drucken vorzuziehen ist?

Zum Beispiel arbeite ich an einer kleinen Funktion, die Sterne im Pyramidenformat druckt, wenn die Zahl als Argument übergeben wird. Obwohl Sie dies mit end = "" erreichen können , um in einer separaten Zeile zu drucken, habe ich sys.stdout.write in Koordination verwendet mit Druck , damit dies funktioniert. Um dies zu erläutern, wird stdout.write in derselben Zeile gedruckt , wobei print den Inhalt immer in einer separaten Zeile druckt.

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

Gibt es Situationen, in denen sys.stdout.write () dem Drucken vorzuziehen ist?

Ich habe festgestellt, dass stdout in einer Multithreading-Situation besser funktioniert als das Drucken. Ich verwende Queue (FIFO), um die zu druckenden Zeilen zu speichern, und halte alle Threads vor der Druckzeile, bis mein Druck-Q leer ist. Trotzdem verliere ich beim Drucken manchmal das letzte \ n der Debug-E / A (mit Wing Pro IDE).

Wenn ich std.out mit \ n in der Zeichenfolge verwende, werden die Debug-E / A-Formate korrekt angezeigt und die \ n werden genau angezeigt.


Kennen Sie einen Grund, warum stdout in diesem Fall besser funktionieren sollte als print, oder ist dies anekdotisch? Könnten Sie ein minimales Arbeitsbeispiel liefern, in dem dies geschieht?
user2653663

Ich denke, dass stdout auf einer niedrigeren Ebene als print funktioniert. Ich hatte definitiv eine Thread-Beschädigung, da zwei Druckroutinen darum kämpften, durch stdout zu gelangen. Das Schreiben an stdout one aus jedem Thread beseitigte die Beschädigung für mich.
David Poundall


1

In Python 3 gibt es einen gültigen Grund für die Verwendung von print over sys.stdout.write. Dieser Grund kann jedoch auch in einen Grund für die Verwendung umgewandelt sys.stdout.writewerden.

Dieser Grund ist, dass jetzt Drucken eine Funktion in Python 3 ist, die Sie überschreiben können. So können Sie print überall in einem einfachen Skript verwenden und entscheiden, in welche print-Anweisungen stderrstattdessen geschrieben werden soll. Sie können die Druckfunktion jetzt einfach neu definieren. Sie können die Druckfunktion sogar global ändern, indem Sie sie mithilfe des integrierten Moduls ändern. Natürlich file.writekönnen Sie bei angeben, was eine Datei ist, aber beim Überschreiben von print können Sie auch das Zeilentrennzeichen oder das Argumenttrennzeichen neu definieren.

Der umgekehrte Weg ist. Vielleicht sind Sie sich absolut sicher, dass Sie schreiben stdout, wissen aber auch, dass Sie den Druck in etwas anderes ändern werden. Sie können sich für die Verwendung entscheiden sys.stdout.writeund print für das Fehlerprotokoll oder etwas anderes verwenden.

Was Sie also verwenden, hängt davon ab, wie Sie es verwenden möchten. printist flexibler, aber das kann ein Grund sein, es zu benutzen und nicht zu benutzen. Ich würde mich stattdessen immer noch für Flexibilität entscheiden und Drucken wählen. Ein weiterer Grund für die Verwendung printist die Vertrautheit. Mehr Menschen werden jetzt wissen, was Sie unter Druck verstehen, und weniger wissen es sys.stdout.write.


1

Einer der Unterschiede ist der folgende, wenn versucht wird, ein Byte in seine hexadezimale Darstellung zu drucken. Zum Beispiel wissen wir , dass Dezimalwert 255ist 0xFFin Hexadezimal Aussehen:

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

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

Darum geht es hier nicht. Dies würde nur in einer interaktiven Shell geschehen, und da ... der Rückgabewert der Funktion (Anzahl der geschriebenen Zeichen), die hexadezimale Darstellung oder andere angezeigte Inhalte write()nicht hinzugefügt \nund zurückgegeben wurden (und die interaktive Shell angezeigt wird), ist dies unerheblich.
Ondrej K.

0

Wenn Sie in Python 2 eine Funktion übergeben müssen, können Sie einer Variablen os.sys.stdout.write zuweisen. Dies können Sie (in der Antwort) nicht mit print tun.

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

Das funktioniert wie erwartet.

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

Das funktioniert nicht. Druck ist eine magische Funktion.


0

Ein Unterschied zwischen printund sys.stdout.writein Python 3 ist auch der Wert, der bei der Ausführung im Terminal zurückgegeben wird. In Python 3 wird sys.stdout.writedie Länge des Strings zurückgegeben, während printnur zurückgegeben wird None.

Wenn Sie beispielsweise folgenden Code interaktiv im Terminal ausführen, wird die Zeichenfolge gefolgt von ihrer Länge ausgedruckt, da die Länge zurückgegeben und ausgegeben wird, wenn sie interaktiv ausgeführt wird:

>>> sys.stdout.write(" hi ")
 hi 4
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.