Sự khác biệt giữa sys.stdout.write và in?


376

Có những tình huống trong đó sys.stdout.write()là thích hợp hơn print?

( Ví dụ: hiệu suất tốt hơn; mã có ý nghĩa hơn)


4
Phiên bản nào của Python? 2.x hay 3.x?
Mark Byers

Thành thật mà nói tôi muốn biết cho cả hai, mặc dù tôi không có kinh nghiệm với Python 3. Đã cập nhật câu hỏi.
Johanna Larsson

17
@ S.Lott: hỏi về sự khác biệt cơ bản giữa sys.stdout.write()print(và / hoặc tại sao Python có cả hai) là một câu hỏi hoàn toàn hợp lý và không cần ví dụ. OP không nói cú pháp lệnh là khó hiểu.
smci

Câu trả lời:


294

printchỉ là một trình bao bọc mỏng định dạng các đầu vào (có thể sửa đổi, nhưng theo mặc định có khoảng trắng giữa args và newline ở cuối) và gọi hàm ghi của một đối tượng đã cho. Theo mặc định, đối tượng này là sys.stdout, nhưng bạn có thể truyền tệp bằng biểu mẫu "chevron". Ví dụ:

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

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


Trong Python 3.x, printtrở thành một hàm, nhưng vẫn có thể vượt qua một cái gì đó ngoài sys.stdoutnhờ vào fileđối số.

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

Xem https://docs.python.org/3/l Library / fiances.html # print


Trong Python 2.6+, printvẫn là một câu lệnh, nhưng nó có thể được sử dụng như một hàm với

from __future__ import print_function

Cập nhật: Bakuriu nhận xét để chỉ ra rằng có một sự khác biệt nhỏ giữa chức năng in và câu lệnh in (và nói chung hơn là giữa chức năng và câu lệnh).

Trong trường hợp có lỗi khi đánh giá đối số:

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
Điều đáng chú ý là printcũng thêm một dòng mới vào bất cứ điều gì bạn viết không xảy ra sys.stdout.write.
Michael Mior

5
Cũng sys.stdout.writephổ biến hơn nếu bạn cần viết mã phiên bản kép (ví dụ mã hoạt động đồng thời với Python 2.x cũng như Python 3.x).
andreb

3
@MichaelMior Bạn có thể chặn dòng mới printnối thêm dấu phẩy:print "this",; print "on the same line as this"
drevicko

1
@ bjd2385 Đây >>không phải là toán tử rshift ở đây mà là một dạng "chevron" cụ thể của printcâu lệnh. Xem docs.python.org/2/reference/ trộm
luc

5
sys.stdout.write()cũng đệm đầu vào và có thể không xóa đầu vào fd ngay lập tức. để đảm bảo rằng nó hoạt động giống như chức năng in, bạn nên thêm: sys.stdout.flush()
kerbelp

151

printđầu tiên chuyển đổi đối tượng thành một chuỗi (nếu nó chưa phải là một chuỗi). Nó cũng sẽ đặt một khoảng trắng trước đối tượng nếu nó không phải là bắt đầu của một dòng và một ký tự dòng mới ở cuối.

Khi sử dụng stdout, bạn cần tự chuyển đổi đối tượng thành một chuỗi (bằng cách gọi "str" ​​chẳng hạn) và không có ký tự dòng mới.

Vì thế

print 99

tương đương với:

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

32
+1 để đề cập đến nhân vật dòng mới! Đây là sự khác biệt chính giữa print.write(), tôi muốn nói.
Eric O Lebigot

9
LƯU Ý: printcó thể được thực hiện để bỏ qua dòng mới. Trong Python 2.x, đặt dấu phẩy ở cuối và ký tự khoảng trắng sẽ được xuất ra, nhưng không có dòng mới. Ví dụ: print 99,Trong Python 3, print(..., end='')sẽ tránh thêm dòng mới (và cũng tránh thêm không gian, trừ khi bạn làm end=' '.
ToolmakerSteve

40
@EOL Thật buồn cười là, ai đó tên EOL đưa ra nhận xét về '\ n' ... Nó làm tôi cười. Tôi không có cuộc sống. Giết tôi đi.
Depado

2
Điều đó KHÔNG đúng, printhoạt động hoạt động hơi khác trong trình xử lý tín hiệu trong python2.X, tức là không thể thay thế in bằng sys.stdout: stackoverflow.com/questions/10777610/
ddzialak

41

Câu hỏi của tôi là có hay không có tình huống nào sys.stdout.write()thích hợp hơn print

Sau khi hoàn thành việc phát triển một kịch bản vào một ngày khác, tôi đã tải nó lên một máy chủ unix. Tất cả các thông báo gỡ lỗi của tôi đã sử dụng các printcâu lệnh và chúng không xuất hiện trên nhật ký máy chủ.

Đây là một trường hợp mà bạn có thể cần sys.stdout.writethay thế.


8
Huh? Bạn có chắc chắn đây là một sự khác biệt giữa print()sys.stdout.write(), trái ngược với sự khác biệt giữa stdoutstderr? Để gỡ lỗi, bạn nên sử dụng loggingmô-đun in thông báo stderr.
Ostrokach

1
Ya. Điều tương tự cũng đúng với việc sử dụng nohupvà chuyển hướng đến một .outtập tin.
conner.xyz

1
sử dụng sys.stdout.flush () sẽ giúp ích.
suprit chaudhary

Nếu bạn sử dụng nohup, theo mặc định, tất cả các văn bản đến stdoutstderrsẽ được chuyển hướng đến nohup.out, không quan tâm đến việc bạn sử dụng printhay stdout.write.
Trịnh Lưu

40

Đây là một số mã mẫu dựa trên cuốn sách Học Python của Mark Lutz giải quyết câu hỏi của bạn:

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

Mở log.txt trong trình soạn thảo văn bản sẽ tiết lộ những điều sau:

testing123
another line

Có cách nào để tôi có thể in ra màn hình cũng như ghi vào tập tin không?
Devesh Saini

5
@DeveshSaini: Có, chỉ cần ghi đè sys.stdout bằng một lớp proxy có ít nhất một hàm write () và flush (). Tôi đã viết một đoạn ví dụ ở đây .
ponycat

14

Có ít nhất một tình huống mà bạn muốn sys.stdoutthay vì in.

Ví dụ, khi bạn muốn ghi đè lên một dòng mà không đi đến dòng tiếp theo trong khi vẽ thanh tiến trình hoặc thông báo trạng thái , bạn cần lặp lại một cái gì đó như

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

Và vì in thêm một dòng mới, bạn nên sử dụng sys.stdout.


2
Nếu in thêm một dòng mới, tại sao không chỉ in ('message', end = '')?
Apoorv Patne

8

Câu hỏi của tôi là có hay không có tình huống nào sys.stdout.write()thích hợp hơnprint

Nếu bạn đang viết một ứng dụng dòng lệnh có thể ghi vào cả hai tệp và thiết bị xuất chuẩn thì thật tiện dụng. Bạn có thể làm những việc như:

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

Điều đó có nghĩa là bạn không thể sử dụng with open(outfile, 'w') as out:mô hình, nhưng đôi khi nó đáng giá.


Nói đúng ra, bạn có thể sử dụng with- def process(output): # .../ if outfile is None: process(sys.stdout) else: with open(outfile, 'w') as out: process(out)(thêm dòng mới khi cần thiết tất nhiên). Nó chắc chắn không sạch lắm, tuy nhiên, đó là điều chắc chắn.
Vụ kiện của Quỹ Monica

4

Trong 2.x, printcâu lệnh xử lý trước những gì bạn cung cấp cho nó, biến nó thành các chuỗi trên đường đi, xử lý các dấu tách và dòng mới và cho phép chuyển hướng đến một tệp. 3.x biến nó thành một chức năng, nhưng nó vẫn có cùng trách nhiệm.

sys.stdout là một tệp hoặc giống như tệp có các phương thức để ghi vào đó có các chuỗi hoặc một cái gì đó dọc theo dòng đó.


3

tốt hơn là khi in động là hữu ích, ví dụ, để cung cấp thông tin trong một quy trình dài:

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 = '') thay vì sys.stdout.write (time_msg) sys.stdout.flush () cũng hoạt động
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

Quan sát ví dụ trên:

  1. sys.stdout.writesẽ không viết đối tượng không phải chuỗi, nhưng printsẽ

  2. sys.stdout.writecuối cùng sẽ không thêm biểu tượng dòng mới, nhưng printsẽ

Nếu chúng ta lặn sâu,

sys.stdout là một đối tượng tệp có thể được sử dụng cho đầu ra của print ()

nếu đối số tệp của print()không được chỉ định, sys.stdoutsẽ được sử dụng


1

Có những tình huống trong đó sys.stdout.write () thích hợp hơn để in không?

Ví dụ: tôi đang làm việc với chức năng nhỏ in các ngôi sao ở định dạng kim tự tháp khi truyền số làm đối số, mặc dù bạn có thể thực hiện điều này bằng cách sử dụng end = "" để in trong một dòng riêng biệt, tôi đã sử dụng sys.stdout.write để phối hợp với bản in để thực hiện công việc này. Để giải thích chi tiết về stdout.write này in cùng một dòng trong đó bản in luôn in nội dung của nó trong một dòng riêng biệt.

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

Có những tình huống trong đó sys.stdout.write () thích hợp hơn để in không?

Tôi đã thấy rằng thiết bị xuất chuẩn hoạt động tốt hơn so với in trong tình huống đa luồng. Tôi sử dụng Hàng đợi (FIFO) để lưu trữ các dòng để in và tôi giữ tất cả các chủ đề trước dòng in cho đến khi Q in của tôi trống. Mặc dù vậy, sử dụng in đôi khi tôi bị mất \ n cuối cùng trên I / O gỡ lỗi (sử dụng IDE pro pro).

Khi tôi sử dụng std.out với \ n trong chuỗi, các định dạng I / O gỡ lỗi chính xác và \ n được hiển thị chính xác.


Bạn có biết lý do tại sao thiết bị xuất chuẩn sẽ hoạt động tốt hơn in trong trường hợp này hay đây là giai thoại? Bạn có thể cung cấp một ví dụ làm việc tối thiểu khi điều này xảy ra?
dùng2653663

Suy nghĩ của tôi là thiết bị xuất chuẩn hoạt động ở mức thấp hơn so với in. Tôi chắc chắn đã có tham nhũng chủ đề khi hai thói quen in đang chiến đấu để ăn qua thiết bị xuất chuẩn. Viết cho thiết bị xuất chuẩn từ mỗi luồng đã loại bỏ tham nhũng cho tôi.
David Poundall


1

Trong Python 3 có lý do hợp lệ để sử dụng in sys.stdout.write, nhưng lý do này cũng có thể được biến thành lý do để sử dụng sys.stdout.writethay thế.

Lý do này là, bây giờ in là một hàm trong Python 3, bạn có thể ghi đè lên điều này. Vì vậy, bạn có thể sử dụng in ở mọi nơi trong một tập lệnh đơn giản và quyết định những câu lệnh in đó cần phải viết để stderrthay thế. Bây giờ bạn có thể chỉ cần xác định lại chức năng in, thậm chí bạn có thể thay đổi chức năng in toàn cầu bằng cách thay đổi nó bằng mô-đun dựng sẵn. Dĩ nhiên với file.writebạn có thể chỉ định tệp là gì, nhưng với phần ghi đè, bạn cũng có thể xác định lại dấu phân cách dòng hoặc dấu phân cách đối số.

Cách khác là xung quanh. Có thể bạn hoàn toàn chắc chắn bạn viết thư stdout, nhưng cũng biết bạn sẽ thay đổi in sang một thứ khác, bạn có thể quyết định sử dụng sys.stdout.writevà sử dụng in cho nhật ký lỗi hoặc một cái gì đó khác.

Vì vậy, những gì bạn sử dụng phụ thuộc vào cách bạn định sử dụng nó. printlinh hoạt hơn, nhưng đó có thể là một lý do để sử dụng và không sử dụng nó. Tôi vẫn sẽ chọn sự linh hoạt thay vào đó, và chọn in. Một lý do khác để sử dụng printthay vì là sự quen thuộc. Nhiều người sẽ biết ý của bạn bằng cách in và ít biết hơn sys.stdout.write.


1

Một trong những khác biệt là như sau, khi cố gắng in một byte thành hình lục giác của nó. Ví dụ, chúng ta biết rằng giá trị thập phân của 2550xFFvề hình dạng thập lục phân:

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

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

Đó không phải là điều này. Nó chỉ xảy ra trong một vỏ tương tác và bởi vì ... write()không thêm \nvà trả về (và hiển thị vỏ tương tác) giá trị trả về của hàm (số ký tự được viết), biểu diễn thập lục phân hoặc bất kỳ nội dung nào khác được hiển thị là không quan trọng.
Ondrej K.

0

Trong python 2 nếu bạn cần chuyển qua một hàm thì bạn có thể gán os.sys.stdout.write cho một biến, bạn không thể thực hiện điều này (trong phần thay thế) bằng in.

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

Điều đó làm việc như mong đợi.

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

Điều đó không làm việc. in là một chức năng kỳ diệu.


0

Một sự khác biệt giữa printsys.stdout.writeđể chỉ ra trong Python 3, cũng là giá trị được trả về khi được thực thi trong terminal. Trong Python 3 sys.stdout.writetrả về chiều dài của chuỗi trong khi printtrả về chỉ None.

Vì vậy, ví dụ chạy mã theo sau một cách tương tác trong thiết bị đầu cuối sẽ in ra chuỗi theo sau bởi chiều dài của nó, vì chiều dài được trả về và xuất ra khi chạy tương tác:

>>> sys.stdout.write(" hi ")
 hi 4
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.