Разница между 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
Luc
источник
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взамен.

LiamSullivan
источник
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.

Carlos
источник
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)
Shivid
источник
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будет использован

GraceMeng
источник
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)
Sree
источник
1

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

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

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

Дэвид Паундалл
источник
Знаете ли вы какую-либо причину, по которой stdout должен работать лучше, чем print в этом случае, или это анекдотично? Не могли бы вы привести минимальный рабочий пример, где это происходит?
user2653663
Я думаю, что стандартный вывод работает на более низком уровне, чем печать. У меня определенно была повреждена нить, так как две программы печати боролись за пропуск через стандартный вывод. Запись в stdout по одному из каждого потока убрала для меня порчу.
Дэвид Паундалл
stackoverflow.com/questions/7877850/…
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
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
truthadjustr
источник
Дело не в этом. Это может произойти только в интерактивной оболочке, и поскольку ... 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

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

shanecandoit
источник
0

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

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

>>> sys.stdout.write(" hi ")
 hi 4
Армандо Андрес Флорес
источник