Разница между sys.stdout.write и print?


376

Существуют ли ситуации, в которых sys.stdout.write()предпочтительнее print?

( Примеры: лучшая производительность; код, который имеет больше смысла)


4
Какая версия Python? 2.x или 3.x?
— Марк Байерс

Честно говоря, я хотел бы знать для обоих, хотя у меня нет опыта работы с Python 3. Обновил вопрос.
— Джоанна Ларссон

17
@ S.Lott: вопрос об основных различиях между sys.stdout.write()и print(и / или почему в Python есть оба) - вполне разумный вопрос и не нуждается в примерах. OP не сказал, что синтаксис команды сбивает с толку.
— smci

Ответы:


294

printэто просто тонкая оболочка, которая форматирует входные данные (изменяемые, но по умолчанию с пробелом между аргументами и символом новой строки в конце) и вызывает функцию записи для данного объекта. По умолчанию этот объект есть sys.stdout, но вы можете передать файл, используя форму «шеврон». Например:

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

Смотрите: https://docs.python.org/2/reference/simple_stmts.html?highlight=print#the-print-statement


В Python 3.x printстановится функцией, но все еще возможно передать что-то иное, чем sys.stdoutблагодаря fileаргументу.

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

См. Https://docs.python.org/3/library/functions.html#print.


В Python 2.6+ printэто все еще оператор, но его можно использовать как функцию с

from __future__ import print_function

Обновление: Бакуриу прокомментировал, что указал на небольшую разницу между функцией печати и оператором печати (и, в более общем смысле, между функцией и оператором).

В случае ошибки при оценке аргументов:

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
Стоит также отметить, что printк тому, что вы пишете, добавляется новая строка, чего не происходит sys.stdout.write.
— Майкл Миор

5
Также sys.stdout.writeболее универсален, если вам когда-либо понадобится написать код с двумя версиями (например, код, который работает одновременно с Python 2.x и Python 3.x).
— andreb

3
@MichaelMior Вы можете подавить символ новой строки, который printдобавляется через запятую:print "this",; print "on the same line as this"
— drevicko

1
@ bjd2385 Здесь >>не оператор rshift, а особая форма «шеврона» printоператора. См docs.python.org/2/reference/...
— Luc

5
sys.stdout.write()также буферизует ввод и может не сразу сбрасывать ввод в fd. чтобы убедиться, что он работает как функция печати, вы должны добавить: sys.stdout.flush()
— kerbelp

151

printсначала преобразует объект в строку (если это еще не строка). Он также будет ставить пробел перед объектом, если это не начало строки и символ новой строки в конце.

При использовании stdoutвам необходимо преобразовать объект в строку самостоятельно (например, вызвав "str"), а символ перевода строки отсутствует.

Так

print 99

эквивалентно:

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

32
+1 за упоминание символа новой строки! Это главное различие между printи .write(), я бы сказал.
— Эрик О Лебиго

9
ПРИМЕЧАНИЕ: printможно сделать, чтобы пропустить символ новой строки. В Python 2.x ставьте запятую в конце, и символ пробела будет выводиться, но без новой строки. Например, print 99,в Python 3 вы print(..., end='')будете избегать добавления новой строки (а также избегать добавления пробела, если вы этого не сделаете end=' '.
— ToolmakerSteve

40
@EOL Как забавно, что кто-то по имени EOL делает комментарий о '\ n' ... Это заставило меня смеяться. У меня нет жизни. Убей меня.
— Депадо

2
это НЕ верно, printоперация ведет себя немного иначе в обработчиках сигналов в python2.X, то есть печать не может быть заменена sys.stdout в примере: stackoverflow.com/questions/10777610/…
— ddzialak

41

У меня вопрос, есть ли ситуации, в которых sys.stdout.write()предпочтительнее print

Закончив разработку скрипта на днях, я загрузил его на сервер Unix. Все мои сообщения отладки использовали printоператоры, и они не появляются в журнале сервера.

Это тот случай, когда вам может понадобиться sys.stdout.writeвзамен.


8
да? Вы уверены, что это разница между print()и sys.stdout.write(), в отличие от stdoutи stderr? Для отладки вы должны использовать loggingмодуль, который печатает сообщения stderr.
— Острокач

1
Ya. То же самое верно для использования nohupи перенаправления в .outфайл.
— conner.xyz

1
использование sys.stdout.flush () поможет.
— Суприт Чаудхари

Если вы используете nohup, по умолчанию все записи stdoutи stderrбудут перенаправлены nohup.out, независимо от того, используете ли вы printили stdout.write.
— Чжэн Лю

40

Вот пример кода, основанного на книге « Изучение Python » Марка Лутца (Mark Lutz), в которой рассматривается ваш вопрос:

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

Открытие log.txt в текстовом редакторе покажет следующее:

testing123
another line

Есть ли способ, чтобы я мог печатать на экран, а также записывать в файл?
— Девеш Саини

5
@DeveshSaini: Да, просто перезапишите sys.stdout прокси-классом, который имеет как минимум функции write () и flush (). Я написал пример фрагмента здесь .
— ponycat

14

Есть хотя бы одна ситуация, в которой вы хотите sys.stdoutвместо печати.

Если вы хотите перезаписать строку, не переходя к следующей строке, например, при рисовании индикатора выполнения или сообщения о состоянии , вам нужно перебрать что-то вроде

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

А так как печать добавляет новую строку, вам лучше использовать sys.stdout.


2
Если print добавляет новую строку, почему бы просто не сделать print ('message', end = '')?
— Апурв Патне

8

У меня вопрос, есть ли ситуации, в которых sys.stdout.write()предпочтительнееprint

Если вы пишете приложение командной строки, которое может записывать как в файлы, так и в stdout, то это удобно. Вы можете делать такие вещи, как:

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

Это означает, что вы не можете использовать with open(outfile, 'w') as out:шаблон, но иногда оно того стоит.


Строго говоря, вы можете использовать with- def process(output): # .../ if outfile is None: process(sys.stdout) else: with open(outfile, 'w') as out: process(out)(добавляя при необходимости новые строки). Это определенно не очень чисто, хотя, это точно.
— Фонд Моника иск

4

В 2.x, printоператор предварительно обрабатывает то, что вы ему даете, превращая его в строки по пути, обрабатывая разделители и символы новой строки и разрешая перенаправление в файл. 3.x превращает его в функцию, но у него все те же обязанности.

sys.stdout это файл или подобный ему файл, который имеет методы для записи в него, которые принимают строки или что-то в этом направлении.


3

предпочтительно, когда динамическая печать полезна, например, для предоставления информации в длительном процессе:

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 = '') вместо sys.stdout.write (time_msg) sys.stdout.flush () также работает
— 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

Наблюдая за примером выше:

  1. sys.stdout.writeне будет писать нестроковый объект, но printбудет

  2. sys.stdout.writeне будет добавлять символ новой строки в конце, но printбудет

Если мы погрузимся глубоко,

sys.stdout это файловый объект, который можно использовать для вывода print ()

если аргумент файла print()не указан, sys.stdoutбудет использован


1

В каких ситуациях предпочтительнее печатать sys.stdout.write ()?

Например, я работаю над маленькой функцией, которая печатает звезды в формате пирамиды после передачи числа в качестве аргумента, хотя вы можете сделать это, используя end = "" для печати в отдельной строке, я использовал sys.stdout.write в координации с печатью, чтобы сделать эту работу. Чтобы уточнить это, stdout.write печатает в той же строке, где print всегда печатает свое содержимое в отдельной строке.

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

В каких ситуациях предпочтительнее печатать sys.stdout.write ()?

Я обнаружил, что стандартный вывод работает лучше, чем печать в многопоточном режиме. Я использую очередь (FIFO), чтобы сохранить строки для печати, и держу все нити перед строкой печати, пока моя печать Q не станет пустой. Тем не менее, при использовании print я иногда теряю финал \ n при отладочном вводе-выводе (используя wing pro IDE).

Когда я использую std.out с \ n в строке, отладочный ввод-вывод форматируется правильно, и \ n точно отображаются.


Знаете ли вы какую-либо причину, по которой stdout должен работать лучше, чем print в этом случае, или это анекдотично? Не могли бы вы привести минимальный рабочий пример, где это происходит?
— user2653663

Я думаю, что стандартный вывод работает на более низком уровне, чем печать. У меня определенно была повреждена нить, так как две программы печати боролись за пропуск через стандартный вывод. Запись в stdout по одному из каждого потока убрала для меня порчу.
— Дэвид Паундалл


1

В Python 3 есть веская причина использовать print over sys.stdout.write, но эта причина также может быть превращена в причину для использования sys.stdout.writeвместо.

Это объясняется тем, что теперь печать является функцией в Python 3, вы можете переопределить это. Таким образом, вы можете использовать print везде в простом сценарии и решить, что эти операторы печати должны писать stderrвместо этого. Теперь вы можете просто переопределить функцию печати, вы даже можете изменить глобальную функцию печати, изменив ее с помощью встроенного модуля. Конечно, file.writeвы можете указать, что это за файл, но при перезаписи печати вы также можете переопределить разделитель строк или разделитель аргументов.

И наоборот. Возможно, вы абсолютно уверены, что пишете stdout, но также знаете, что собираетесь изменить печать на что-то другое, вы можете решить использовать sys.stdout.writeи использовать печать для журнала ошибок или чего-то еще.

Итак, что вы используете, зависит от того, как вы собираетесь его использовать. printявляется более гибким, но это может быть причиной, чтобы использовать и не использовать его. Я бы все равно выбрал гибкость и выбрал печать. Еще одна причина, чтобы использовать printвместо этого знакомство. Больше людей теперь поймут, что вы подразумеваете под печатью, и меньше узнаете sys.stdout.write.


1

Одно из различий заключается в следующем, когда вы пытаетесь напечатать байт в его шестнадцатеричном виде. Например, мы знаем , что десятичное значение из 255вне 0xFFв шестнадцатеричном виде:

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

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

Дело не в этом. Это может произойти только в интерактивной оболочке, и поскольку ... write()не добавляется \nи не возвращается (и не отображается интерактивная оболочка) возвращаемое значение функции (количество записанных символов), шестнадцатеричное представление или любое другое отображаемое содержимое несущественно.
— Ондрей К.

0

В Python 2, если вам нужно передать функцию, вы можете присвоить os.sys.stdout.write переменной, вы не можете сделать это (в repl) с помощью print.

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

Это работает, как ожидалось.

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

Это не работает. Печать это магическая функция.


0

Разница между printи sys.stdout.writeуказывать в Python 3, это также значение, которое возвращается при выполнении в терминале. В Python 3 sys.stdout.writeвозвращает длину строки, а printвозвращает просто None.

Так, например, выполнение следующего кода в терминале в интерактивном режиме выведет на печать строку, за которой следует ее длина, поскольку длина возвращается и выводится при интерактивном запуске:

>>> sys.stdout.write(" hi ")
 hi 4
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.