Różnica między sys.stdout.write a print?


375

Czy są sytuacje, w których sys.stdout.write()lepiej jest print?

( Przykłady: lepsza wydajność; kod, który ma większy sens)


4
Która wersja Pythona? 2.x czy 3.x?
Mark Byers

Szczerze, chciałbym wiedzieć o obu, chociaż nie mam doświadczenia z Python 3. Zaktualizowałem pytanie.
Johanna Larsson,

17
@ S.Lott: pytanie o podstawowe różnice między sys.stdout.write()i print(i / lub dlaczego Python ma oba) jest całkowicie rozsądnym pytaniem i nie wymaga przykładów. OP nie powiedział, że składnia polecenia jest myląca.
smci,

Odpowiedzi:


293

printjest tylko cienkim opakowaniem, które formatuje dane wejściowe (modyfikowalne, ale domyślnie ze spacją między argumentami i znakiem nowej linii na końcu) i wywołuje funkcję zapisu danego obiektu. Domyślnie ten obiekt jest sys.stdout, ale plik można przekazać za pomocą formularza „chevron”. Na przykład:

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

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


W Pythonie 3.x printstaje się funkcją, ale nadal można przekazać coś innego niż sys.stdoutdzięki fileargumentowi.

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

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


W Pythonie 2.6+ printwciąż jest instrukcją, ale może być używana jako funkcja z

from __future__ import print_function

Aktualizacja: Bakuriu skomentował, że istnieje niewielka różnica między funkcją print a instrukcją print (a bardziej ogólnie między funkcją a instrukcją).

W przypadku błędu podczas oceny argumentów:

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
Warto również zauważyć, że printdodaje także nowy wiersz do wszystkiego, co piszesz, co się nie zdarza sys.stdout.write.
Michael Mior,

5
sys.stdout.writeJest także bardziej uniwersalny, jeśli kiedykolwiek będziesz musiał napisać kod podwójnej wersji (np. Kod, który działa jednocześnie z Python 2.x oraz Python 3.x).
andreb

3
@MichaelMior Możesz wyłączyć nowy wiersz, który printprint "this",; print "on the same line as this"
uzupełnia go

1
@ bjd2385 Nie >>jest tutaj operatorem rshift, ale specyficzną formą „chevron” printinstrukcji. Zobacz docs.python.org/2/reference/…
luc

5
sys.stdout.write()buforuje również dane wejściowe i może nie natychmiast opróżnić dane wejściowe do fd. aby upewnić się, że zachowuje się jak funkcja drukowania, należy dodać: sys.stdout.flush()
kerbelp

151

printNajpierw konwertuje obiekt na ciąg (jeśli nie jest to już ciąg). Umieści także spację przed obiektem, jeśli nie jest to początek linii i znak nowej linii na końcu.

Podczas używania stdoutmusisz samodzielnie przekonwertować obiekt na ciąg znaków (na przykład przez wywołanie „str”) i nie ma znaku nowej linii.

Więc

print 99

jest równa:

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

32
+1 za wspomnienie o znaku nowej linii! To jest główna różnica między printi .write(), powiedziałbym.
Eric O Lebigot,

9
UWAGA: printmożna wprowadzić pominięcie nowej linii. W Pythonie 2.x umieść przecinek na końcu, a spacja zostanie wypisana, ale nie będzie nowego wiersza. Np. print 99,W Pythonie 3, print(..., end='')unikniesz dodawania nowej linii (a także unikniesz dodawania spacji, chyba że to zrobisz end=' '.
ToolmakerSteve

40
@EOL Jak zabawne jest to, że ktoś o imieniu EOL komentuje „\ n” ... Rozśmieszyło mnie to. Nie mam życia. Zabij mnie.
Depado

2
to NIE jest prawda, printdziałanie zachowuje się nieco inaczej w procedurach obsługi sygnałów w python2.X, tzn. print nie może być zastąpiony przez sys.stdout w przykładzie: stackoverflow.com/questions/10777610/…
ddzialak

41

Moje pytanie brzmi, czy są sytuacje, w których sys.stdout.write()lepiej jest print

Po zakończeniu opracowywania skryptu innego dnia przesłałem go na serwer unix. Wszystkie moje komunikaty debugowania używały printinstrukcji, które nie pojawiają się w dzienniku serwera.

Jest to przypadek, w którym możesz potrzebować sys.stdout.writezamiast tego.


8
co? Czy na pewno jest to różnica między print()i sys.stdout.write(), w przeciwieństwie do różnicy między stdouti stderr? Do debugowania należy użyć loggingmodułu, na którym drukowane są wiadomości stderr.
ostrokach

1
Ya. To samo dotyczy używania nohupi przekierowywania do .outpliku.
conner.xyz

1
użycie sys.stdout.flush () pomogłoby.
suprit chaudhary

Jeśli używasz nohup, domyślnie całe pisanie do stdouti stderrzostanie przekierowane nohup.out, niezależnie od tego, czy używasz, printczy stdout.write.
Zheng Liu,

40

Oto przykładowy kod oparty na książce Learning Python autorstwa Mark Lutz, który odpowiada na twoje pytanie:

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

Otwarcie log.txt w edytorze tekstu ujawni następujące informacje:

testing123
another line

Czy jest jakiś sposób, aby móc drukować na ekranie, a także zapisywać do pliku?
Devesh Saini

5
@DeveshSaini: Tak, po prostu nadpisuj sys.stdout klasą proxy, która ma co najmniej funkcję write () i flush (). Tutaj napisałem przykładowy fragment .
ponycat

14

Jest co najmniej jedna sytuacja, w której chcesz sys.stdoutzamiast drukować.

Jeśli chcesz zastąpić linię bez przechodzenia do następnej linii, na przykład podczas rysowania paska postępu lub komunikatu o stanie , musisz zapętlić coś takiego jak

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

A ponieważ print dodaje nowy wiersz, lepiej jest używać sys.stdout.


2
Jeśli print dodaje nową linię, dlaczego po prostu nie zamiast tego drukuj ('message', end = '')?
Apoorv Patne

8

Moje pytanie brzmi, czy są sytuacje, w których sys.stdout.write()lepiej jestprint

Jeśli piszesz aplikację wiersza polecenia, która może zapisywać zarówno pliki, jak i standardowe wyjście, jest to przydatne. Możesz robić takie rzeczy jak:

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

Oznacza to, że nie możesz użyć tego with open(outfile, 'w') as out:wzoru, ale czasem warto.


Ściśle mówiąc, to można użyć with- def process(output): # .../ if outfile is None: process(sys.stdout) else: with open(outfile, 'w') as out: process(out)(dodawanie nowych linii w razie potrzeby oczywiście). To na pewno niezbyt czyste, to na pewno.
Pozew Fund Moniki w

4

W wersji 2.x printinstrukcja przetwarza to, co dajesz, przekształcając ją w ciągi po drodze, obsługując separatory i znaki nowej linii oraz umożliwiając przekierowanie do pliku. 3.x zamienia go w funkcję, ale nadal ma te same obowiązki.

sys.stdout jest plikiem lub podobnym do pliku, który ma metody zapisu do niego, które pobierają ciągi lub coś wzdłuż tej linii.


3

wskazane jest, gdy przydatne jest drukowanie dynamiczne, na przykład w celu dostarczenia informacji w długim procesie:

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 = '') zamiast tego sys.stdout.write (time_msg) sys.stdout.flush () również działa
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

Obserwując powyższy przykład:

  1. sys.stdout.writenie napisze obiektu nie łańcuchowego, ale printbędzie

  2. sys.stdout.writenie doda nowego symbolu linii na końcu, ale printzrobi to

Jeśli zanurzymy się głęboko,

sys.stdout to obiekt pliku, którego można użyć do wydruku print ()

jeśli print()nie określono argumentu pliku , sys.stdoutzostanie użyty


1

Czy istnieją sytuacje, w których sys.stdout.write () jest preferowane do drukowania?

Na przykład pracuję nad małą funkcją, która drukuje gwiazdy w formacie piramidy po przekazaniu liczby jako argumentu, chociaż możesz to zrobić za pomocą end = "", aby wydrukować w osobnej linii, użyłem sys.stdout.write w koordynacji z nadrukiem, aby to zadziałało. Aby rozwinąć tę kwestię, stdout.write drukuje w tej samej linii, gdzie jako print zawsze drukuje jej zawartość w osobnej linii.

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

Czy istnieją sytuacje, w których sys.stdout.write () jest preferowane do drukowania?

Przekonałem się, że standardowe wyjście działa lepiej niż drukowanie w sytuacji wielowątkowości. Używam kolejki (FIFO) do przechowywania linii do wydrukowania i trzymam wszystkie wątki przed linią drukowania, aż mój wydruk Q będzie pusty. Mimo to, używając print, czasami tracę końcowy \ n debugowania I / O (używając wing pro IDE).

Kiedy używam std.out z \ n w ciągu, debugowane we / wy formatuje poprawnie, a \ n są dokładnie wyświetlane.


Czy znasz jakiś powód, dla którego stdout powinien działać lepiej niż drukowanie w tym przypadku, czy jest to anegdota? Czy możesz podać minimalny działający przykład, w którym to się dzieje?
user2653663,

Myślę, że standardowe wyjście działa na niższym poziomie niż drukowanie. Zdecydowanie miałem uszkodzenie wątku, ponieważ dwie procedury drukowania walczyły o przejście przez standardowe wyjście. Pisanie na stdout po jednym z każdego wątku usunęło dla mnie zepsucie.
David Poundall,


1

W Pythonie 3 istnieje prawidłowy powód, dla którego warto zastosować print sys.stdout.write, ale ten powód można również zmienić w powód do użyciasys.stdout.write zamiast tego.

Powodem jest to, że teraz print jest funkcją w Pythonie 3, możesz to zmienić. Możesz więc używać print wszędzie w prostym skrypcie i zdecydować, że te instrukcje drukowania muszą pisać w stderrzamian. Teraz możesz po prostu przedefiniować funkcję drukowania, możesz nawet zmienić funkcję drukowania globalną, zmieniając ją za pomocą wbudowanego modułu. Oczywiście, że zfile.write możesz określić, co to jest plik, ale w przypadku nadpisywania wydruku możesz również przedefiniować separator linii lub separator argumentów.

Odwrotnie jest. Być może jesteś absolutnie pewien, że piszesz stdout, ale wiesz również, że zamierzasz zmienić druk na coś innego, z czego możesz zdecydować się skorzystaćsys.stdout.write i użyj print do dziennika błędów lub czegoś innego.

To, czego używasz, zależy od tego, jak zamierzasz go używać. printjest bardziej elastyczny, ale może to być powód do korzystania i nieużywania go. Nadal wybrałbym elastyczność i wybrałbym druk. Innym powodem użycia printzamiast tego jest znajomość. Więcej osób zrozumie teraz, co masz na myśli przez druk, a mniej wie sys.stdout.write.


1

Jedną z różnic jest to, że podczas próby wydrukowania bajtu w jego szesnastkowym wyglądzie. Na przykład wiemy, że wartość dziesiętna 255ma 0xFFwygląd szesnastkowy:

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

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

Nie o to chodzi. Działo się tak tylko w interaktywnej powłoce, ponieważ ... write()nie dodawała \ni nie zwraca (i interaktywne wyświetlanie powłoki) wartości zwracanej przez funkcję (liczba zapisanych znaków), reprezentacji szesnastkowej lub jakiejkolwiek innej wyświetlanej treści jest nieistotna.
Ondrej K.

0

W Pythonie 2, jeśli chcesz przekazać funkcję, możesz przypisać os.sys.stdout.write do zmiennej, nie możesz tego zrobić (w replice) za pomocą print.

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

To działa zgodnie z oczekiwaniami.

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

To nie działa. druk jest magiczną funkcją.


0

Różnica między printi, sys.stdout.writeaby wskazać w Pythonie 3, to także wartość zwracana po wykonaniu w terminalu. W Pythonie 3 sys.stdout.writezwraca długość ciągu, podczas gdy printzwraca tylkoNone .

Na przykład uruchomienie interaktywnego kodu w terminalu wypisuje ciąg znaków wraz z jego długością, ponieważ długość jest zwracana i wyprowadzana po uruchomieniu interaktywnym:

>>> sys.stdout.write(" hi ")
 hi 4
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.