Perbedaan antara sys.stdout.write dan cetak?

376

Apakah ada situasi yang sys.stdout.write()lebih disukai print?

( Contoh: kinerja yang lebih baik; kode yang lebih masuk akal)

Johanna Larsson
sumber
4
Versi Python yang mana? 2.x atau 3.x?
Mark Byers
Jujur saya ingin tahu untuk keduanya, meskipun saya tidak punya pengalaman dengan Python 3. Diperbarui pertanyaannya.
Johanna Larsson
17
@ S.Lott: menanyakan perbedaan mendasar antara sys.stdout.write()dan print(dan / atau mengapa Python memiliki keduanya) adalah pertanyaan yang sangat masuk akal dan tidak perlu contoh. OP tidak mengatakan sintaks perintah membingungkan.
smci

Jawaban:

294

printhanyalah pembungkus tipis yang memformat input (dapat dimodifikasi, tetapi secara default dengan spasi antara args dan baris baru di akhir) dan memanggil fungsi tulis dari objek yang diberikan. Secara default objek ini sys.stdout, tetapi Anda dapat mengirimkan file menggunakan formulir "chevron". Sebagai contoh:

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

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


Dalam Python 3.x, printmenjadi fungsi, tetapi masih mungkin untuk melewatkan sesuatu selain sys.stdoutberkat fileargumennya.

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

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


Dalam Python 2.6+, printmasih merupakan pernyataan, tetapi dapat digunakan sebagai fungsi dengan

from __future__ import print_function

Pembaruan: Bakuriu berkomentar untuk menunjukkan bahwa ada perbedaan kecil antara fungsi cetak dan pernyataan cetak (dan lebih umum antara fungsi dan pernyataan).

Jika terjadi kesalahan saat mengevaluasi argumen:

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
luc
sumber
64
Perlu juga dicatat bahwa printjuga menambahkan baris baru ke apa pun yang Anda tulis yang tidak terjadi sys.stdout.write.
Michael Mior
5
Juga sys.stdout.writelebih universal jika Anda perlu menulis kode versi ganda (mis. Kode yang bekerja secara bersamaan dengan Python 2.x dan juga Python 3.x).
andreb
3
@MichaelMior Anda dapat menekan baris baru yang printditambahkan dengan tanda koma:print "this",; print "on the same line as this"
drevicko
1
@ bjd2385 Ini >>bukan operator rshift di sini tetapi bentuk "chevron" spesifik dari printpernyataan. Lihat docs.python.org/2/reference/…
luc
5
sys.stdout.write()juga buffer input dan mungkin tidak segera menyiram input ke fd. untuk memastikan bahwa ia berperilaku seperti fungsi cetak, Anda harus menambahkan: sys.stdout.flush()
kerbelp
151

printpertama-tama mengonversi objek ke string (jika belum menjadi string). Ini juga akan menempatkan spasi di depan objek jika itu bukan awal dari sebuah baris dan karakter baris baru di akhir.

Ketika menggunakan stdout , Anda perlu mengonversi objek ke string sendiri (dengan memanggil "str", misalnya) dan tidak ada karakter baris baru.

Begitu

print 99

setara dengan:

import sys
sys.stdout.write(str(99) + '\n')
dogbane
sumber
32
+1 untuk menyebutkan karakter baris baru! Inilah perbedaan utama antara printdan .write(), saya katakan.
Eric O Lebigot
9
CATATAN: printdapat dibuat untuk menghilangkan baris baru. Dalam Python 2.x, beri koma di akhir, dan karakter spasi akan ditampilkan, tetapi tidak ada baris baru. Misalnya print 99,Dalam Python 3, print(..., end='')akan menghindari penambahan baris baru (dan juga menghindari penambahan ruang, kecuali jika Anda melakukannya end=' '.
ToolmakerSteve
40
@ EOL Betapa lucunya itu, bahwa seseorang bernama EOL membuat komentar tentang '\ n' ... Itu membuat saya tertawa. Saya tidak punya kehidupan. Bunuh aku.
Depado
2
itu TIDAK benar, printoperasi berperilaku sedikit berbeda dalam penangan sinyal di python2.X, yaitu cetak tidak dapat diganti dengan sys.stdout dalam contoh: stackoverflow.com/questions/10777610/…
ddzialak
41

Pertanyaan saya adalah apakah ada situasi yang sys.stdout.write()lebih disukai print

Setelah selesai mengembangkan skrip beberapa hari yang lalu, saya mengunggahnya ke server unix. Semua pesan debug saya menggunakan printpernyataan, dan ini tidak muncul pada log server.

Ini adalah kasus di mana Anda mungkin membutuhkannya sys.stdout.write.

LiamSullivan
sumber
8
Hah? Apakah Anda yakin ini perbedaan antara print()dan sys.stdout.write(), yang bertentangan dengan perbedaan antara stdoutdan stderr? Untuk debugging, Anda harus menggunakan loggingmodul, yang mencetak pesan stderr.
ostrokach
1
Ya Hal yang sama berlaku dengan menggunakan nohupdan mengarahkan ulang ke .outfile.
conner.xyz
1
penggunaan sys.stdout.flush () akan membantu.
suprit chaudhary
Jika Anda menggunakan nohup, secara default semua tulisan ke stdoutdan stderrakan diarahkan kembali ke nohup.out, mengabaikan apakah Anda menggunakan printatau stdout.write.
Zheng Liu
40

Berikut ini beberapa contoh kode berdasarkan buku Learning Python oleh Mark Lutz yang menjawab pertanyaan Anda:

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

Membuka log.txt dalam editor teks akan mengungkapkan hal berikut:

testing123
another line
Will Townes
sumber
Apakah ada cara agar saya dapat mencetak ke layar serta menulis ke file?
Devesh Saini
5
@DeveshSaini: Ya, timpa saja sys.stdout dengan kelas proxy yang memiliki setidaknya fungsi write () dan flush (). Saya menulis cuplikan contoh di sini .
ponycat
14

Setidaknya ada satu situasi di mana Anda ingin sys.stdoutalih-alih mencetak.

Saat Anda ingin menimpa baris tanpa pergi ke baris berikutnya, misalnya saat menggambar bilah kemajuan atau pesan status , Anda perlu mengulang sesuatu seperti

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

Dan karena cetak menambah baris baru, Anda lebih baik menggunakan sys.stdout.

Carlos
sumber
2
Jika cetak menambahkan baris baru mengapa tidak hanya mencetak ('message', end = '')?
Apoorv Patne
8

Pertanyaan saya adalah apakah ada situasi yang sys.stdout.write()lebih disukaiprint

Jika Anda sedang menulis aplikasi baris perintah yang dapat menulis ke kedua file dan stdout maka itu berguna. Anda dapat melakukan hal-hal seperti:

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

Itu berarti Anda tidak dapat menggunakan with open(outfile, 'w') as out:polanya, tetapi terkadang itu sepadan.

Hamish Downer
sumber
Sebenarnya, Anda dapat menggunakan with- def process(output): # .../ if outfile is None: process(sys.stdout) else: with open(outfile, 'w') as out: process(out)(menambahkan baris baru jika perlu tentunya). Ini jelas tidak terlalu bersih, itu sudah pasti.
Dana Gugatan Monica
4

Dalam 2.x, the print pernyataan memproses ulang apa yang Anda berikan, mengubahnya menjadi string di sepanjang jalan, menangani pemisah dan baris baru, dan memungkinkan pengalihan ke file. 3.x mengubahnya menjadi fungsi, tetapi masih memiliki tanggung jawab yang sama.

sys.stdout adalah file atau file-seperti yang memiliki metode untuk menulis kepadanya yang mengambil string atau sesuatu di sepanjang baris itu.

Ignacio Vazquez-Abrams
sumber
3

lebih disukai ketika pencetakan dinamis berguna, misalnya, untuk memberikan informasi dalam proses yang panjang:

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)
Terpisah
sumber
2
cetak (time_msg, end = '') sebagai gantinya sys.stdout.write (time_msg) sys.stdout.flush () juga berfungsi
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

Perhatikan contoh di atas:

  1. sys.stdout.writetidak akan menulis objek non-string, tetapi printakan

  2. sys.stdout.writetidak akan menambahkan simbol baris baru pada akhirnya, tetapi printakan

Jika kita menyelam dalam-dalam,

sys.stdout adalah objek file yang dapat digunakan untuk output dari print ()

jika argumen file print()tidak ditentukan, sys.stdoutakan digunakan

GraceMeng
sumber
1

Apakah ada situasi di mana sys.stdout.write () lebih baik dicetak?

Misalnya saya sedang mengerjakan fungsi kecil yang mencetak bintang dalam format piramida setelah melewati angka sebagai argumen, meskipun Anda dapat melakukannya menggunakan end = "" untuk mencetak dalam baris terpisah, saya menggunakan sys.stdout.write dalam koordinasi dengan cetak untuk membuat ini berfungsi. Untuk menguraikan stdout.write ini mencetak di baris yang sama di mana sebagai cetak selalu mencetak isinya dalam baris yang terpisah.

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)
Sree
sumber
1

Apakah ada situasi di mana sys.stdout.write () lebih baik dicetak?

Saya telah menemukan bahwa stdout berfungsi lebih baik daripada mencetak dalam situasi multithreading. Saya menggunakan Antrian (FIFO) untuk menyimpan garis untuk dicetak dan saya memegang semua utas sebelum garis cetak sampai Q cetak saya kosong. Meski begitu, menggunakan print saya terkadang kehilangan final \ n pada debug I / O (menggunakan wing pro IDE).

Ketika saya menggunakan std.out dengan \ n dalam string, debug I / O format dengan benar dan \ n's ditampilkan secara akurat.

David Poundall
sumber
Apakah Anda tahu alasan mengapa stdout harus bekerja lebih baik daripada mencetak dalam hal ini, atau ini anekdotal? Bisakah Anda memberikan contoh kerja minimal di mana ini terjadi?
user2653663
Pemikiran saya adalah stdout bekerja pada level yang lebih rendah daripada print. Saya benar-benar mengalami korupsi thread karena dua rutinitas cetak berjuang untuk memberi makan melalui stdout. Menulis ke stdout satu dari setiap utas menghapus korupsi untuk saya.
David Poundall
stackoverflow.com/questions/7877850/…
Ciro Santilli 郝海东 冠状 病 六四 事件 事件 法轮功
1

Di Python 3 ada alasan yang sah untuk menggunakan print over sys.stdout.write, tetapi alasan ini juga bisa dijadikan alasan untuk menggunakannya sys.stdout.write.

Alasannya adalah, sekarang cetak adalah fungsi dengan Python 3, Anda dapat menimpanya. Jadi, Anda dapat menggunakan cetak di mana-mana dalam skrip sederhana dan memutuskan pernyataan cetak itu perlu ditulis stderr. Anda sekarang dapat mendefinisikan ulang fungsi cetak, Anda bahkan dapat mengubah fungsi cetak global dengan mengubahnya menggunakan modul bawaan. Tentu saja denganfile.write Anda dapat menentukan file apa, tetapi dengan mencetak overwriting Anda juga dapat mendefinisikan ulang pemisah baris, atau pemisah argumen.

Sebaliknya adalah. Mungkin Anda benar-benar yakin untuk menulis surat stdout, tetapi juga tahu Anda akan mengubah cetakan menjadi sesuatu yang lain, Anda dapat memutuskan untuk menggunakannyasys.stdout.write , dan menggunakan cetak untuk log kesalahan atau sesuatu yang lain.

Jadi, apa yang Anda gunakan tergantung pada bagaimana Anda bermaksud menggunakannya. printlebih fleksibel, tetapi itu bisa menjadi alasan untuk menggunakan dan tidak menggunakannya. Saya masih akan memilih fleksibilitas, dan memilih cetak. Alasan lain untuk menggunakan printgantinya adalah keakraban. Semakin banyak orang sekarang akan apa yang Anda maksud dengan cetak dan kurang tahu sys.stdout.write.

Hielke Walinga
sumber
1

Salah satu perbedaannya adalah sebagai berikut, ketika mencoba mencetak byte ke tampilan heksadesimalnya. Sebagai contoh, kita tahu bahwa nilai desimal 255adalah 0xFFdalam penampilan heksadesimal:

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

sys.stdout.write(val) # prints ff2
print(val)            # prints ff
kebenaranadjustr
sumber
Ini bukan tentang ini. Itu hanya akan terjadi di shell interaktif dan karena ... write()tidak menambah \ndan mengembalikan (dan menampilkan shell interaktif) nilai kembali fungsi (jumlah karakter yang ditulis), representasi heksadesimal atau konten lain yang ditampilkan tidak material.
Ondrej K.
0

Dalam python 2 jika Anda perlu melewati fungsi maka Anda dapat menetapkan os.sys.stdout.write ke variabel, Anda tidak dapat melakukan ini (di repl) dengan cetak.

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

Itu bekerja seperti yang diharapkan.

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

Itu tidak bekerja. cetak adalah fungsi ajaib.

shanecandoit
sumber
0

Perbedaan antara printdan sys.stdout.writeuntuk menunjukkan dalam Python 3, juga nilai yang dikembalikan ketika dieksekusi di terminal. Dalam Python 3 sys.stdout.writemengembalikan panjang string sedangkan printmengembalikan sajaNone .

Jadi misalnya menjalankan kode berikut secara interaktif di terminal akan mencetak string yang diikuti oleh lenght, karena lenght dikembalikan dan dihasilkan ketika dijalankan secara interaktif:

>>> sys.stdout.write(" hi ")
 hi 4
Armando Andres Flores
sumber