Різниця між sys.stdout.write і print?


375

Чи є ситуації, в яких sys.stdout.write()краще print?

( Приклади: краща продуктивність; код має більше сенсу)


4
Яка версія Python? 2.x або 3.x?
Марк Байєрс

Чесно кажучи, я хотів би знати для обох, хоча у мене немає досвіду роботи з Python 3. Оновлено питання.
Йоганна Ларссон

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

Відповіді:


293

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 Ви можете придушити новий рядок, який printprint "this",; print "on the same line as this"
додається

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.
ostrokach

1
Я. Те саме стосується використання nohupта переадресації до .outфайлу.
conner.xyz

1
використання sys.stdout.flush () допомогло б.
suprit chaudhary

Якщо ви використовуєте nohup, за замовчуванням все записування до stdoutта stderrбуде перенаправлено на nohup.out, не зважаючи на те, чи використовуєте ви printчи stdout.write.
Чжен Лю

40

Ось приклад коду, який базується на книзі " Навчання пітона Марка Лутца", яка стосується вашого питання:

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
Якщо друк додає новий рядок, чому б не просто зробити друк ('повідомлення', кінець = '') замість цього?
Апоорв Патне

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 () бажано друкувати?

Я виявив, що stdout працює краще, ніж друк у багатопотокової ситуації. Я використовую чергу (FIFO) для зберігання рядків для друку, і я тримаю всі нитки перед друкованою лінією, поки мій друк Q не буде порожнім. Тим не менш, використовуючи print, я іноді втрачаю остаточний \ n на відладці вводу / виводу (використовуючи крило про IDE).

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


Чи знаєте ви будь-яку причину, чому stdout повинен працювати краще, ніж друк у цьому випадку, чи це анекдотично? Чи можете ви надати мінімальний робочий приклад, коли це відбувається?
user2653663

Думаю, що stdout працює на нижчому рівні, ніж друк. У мене, безумовно, була корупційна нитка, оскільки дві рутини друку боролися за подачу через stdout. Написання в stdout по одному з кожного потоку видалило для мене пошкодження.
Девід Пундалл


1

У Python 3 є поважна причина використання друку sys.stdout.write, але ця причина також може бути перетворена на причину використання sys.stdout.writeзамість цього.

Ця причина полягає в тому, що тепер print - це функція в Python 3, ви можете це змінити. Таким чином, ви можете використовувати друк скрізь у простому сценарії та вирішувати, до яких заяв щодо друку потрібно писати stderr. Тепер ви можете просто переглянути функцію друку, ви навіть можете змінити функцію друку глобально, змінивши її за допомогою вбудованого модуля. Зрозуміло, file.writeви можете вказати, що таке файл, але, перезаписуючи друк, ви також можете визначити роздільник рядків або роздільник аргументів.

Навпаки є. Можливо, ви абсолютно впевнені, що ви пишете stdout, але також знаєте, що збираєтеся змінити друк на щось інше, ви можете вирішити використовувати sys.stdout.writeта використовувати print для журналу помилок чи чогось іншого.

Отже, те, що ви використовуєте, залежить від того, як ви збираєтесь ним користуватися. 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 змінній, ви не можете цього зробити (у відповіді) з друком.

>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.