Есть несколько способов написать в stderr:

# Note: this first one does not work in Python 3
print >> sys.stderr, "spam"

sys.stderr.write("spam\n")

os.write(2, b"spam\n")

from __future__ import print_function
print("spam", file=sys.stderr)

Кажется, это противоречит дзен Python # 13 , так в чем же здесь разница и есть ли преимущества или недостатки в том или ином случае? Какой способ следует использовать?

Должен быть один - и желательно только один - очевидный способ сделать это.

1445
wim 7 Апр 2011 в 04:59

15 ответов

Лучший ответ

Я обнаружил, что это единственный короткий + гибкий + портативный + читаемый:

from __future__ import print_function
import sys

def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

Функцию eprint можно использовать так же, как и стандартную функцию print:

>>> print("Test")
Test
>>> eprint("Test")
Test
>>> eprint("foo", "bar", "baz", sep="---")
foo---bar---baz
1118
Leon 17 Фев 2018 в 19:25
import sys
sys.stderr.write()

Это мой выбор, просто более читаемый и точно говорящий о том, что вы собираетесь делать, и переносимый между версиями.

Изменить: «pythonic» - это третья мысль для меня о читабельности и производительности ... с учетом этих двух вещей, с python 80% вашего кода будет pythonic. понимание списка - это «большая вещь», которая используется не так часто (удобочитаемость).

533
Chris Stryczynski 15 Ноя 2018 в 08:34

Это будет имитировать стандартную функцию печати, но вывод на stderr

def print_err(*args):
    sys.stderr.write(' '.join(map(str,args)) + '\n')
19
Brian W. 6 Окт 2012 в 07:42

Если вы делаете простой тест:

import time
import sys

def run1(runs):
    x = 0
    cur = time.time()
    while x < runs:
        x += 1
        print >> sys.stderr, 'X'
    elapsed = (time.time()-cur)
    return elapsed

def run2(runs):
    x = 0
    cur = time.time()
    while x < runs:
        x += 1
        sys.stderr.write('X\n')
        sys.stderr.flush()
    elapsed = (time.time()-cur)
    return elapsed

def compare(runs):
    sum1, sum2 = 0, 0
    x = 0
    while x < runs:
        x += 1
        sum1 += run1(runs)
        sum2 += run2(runs)
    return sum1, sum2

if __name__ == '__main__':
    s1, s2 = compare(1000)
    print "Using (print >> sys.stderr, 'X'): %s" %(s1)
    print "Using (sys.stderr.write('X'),sys.stderr.flush()):%s" %(s2)
    print "Ratio: %f" %(float(s1) / float(s2))

Вы обнаружите, что sys.stderr.write () всегда в 1,81 раз быстрее!

2
ThePracticalOne 12 Июн 2012 в 17:17

То же самое относится к stdout:

print 'spam'
sys.stdout.write('spam\n')

Как указано в других ответах, print предлагает симпатичный интерфейс, который часто более удобен (например, для печати отладочной информации), тогда как write быстрее и также может быть более удобным, когда Вы должны точно отформатировать вывод. Я бы также рассмотрел ремонтопригодность:

  1. Позже вы можете переключиться между stdout / stderr и обычным файлом.

  2. Синтаксис print () изменился в Python 3, поэтому, если вам нужно поддерживать обе версии, write () может быть лучше.

5
Seppo Enarvi 11 Май 2015 в 16:10

Я сделал следующее, используя Python 3:

from sys import stderr

def print_err(*args, **kwargs):
    print(*args, file=stderr, **kwargs)

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

print_err("Error: end of the file reached. The word ", end='')
print_err(word, "was not found")
32
aaguirre 29 Дек 2013 в 21:45

Я работаю в Python 3.4.3. Я вырезал небольшой набор текста, который показывает, как я попал сюда:

[18:19 jsilverman@JSILVERMAN-LT7 pexpect]$ python3
>>> import sys
>>> print("testing", file=sys.stderr)
testing
>>>
[18:19 jsilverman@JSILVERMAN-LT7 pexpect]$ 

Это сработало? Попробуйте перенаправить stderr в файл и посмотрите, что произойдет:

[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$ python3 2> /tmp/test.txt
>>> import sys
>>> print("testing", file=sys.stderr)
>>> [18:22 jsilverman@JSILVERMAN-LT7 pexpect]$
[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$ cat /tmp/test.txt
Python 3.4.3 (default, May  5 2015, 17:58:45)
[GCC 4.9.2] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
testing

[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$

Ну, кроме того факта, что небольшое введение, которое дает вам Python, было добавлено в stderr (куда еще он пойдет?), Это работает.

4
user1928764 10 Фев 2016 в 02:29

В Python 3 можно просто использовать print ():

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

Почти из коробки:

import sys
print("Hello, world!", file=sys.stderr)

Или же:

from sys import stderr
print("Hello, world!", file=stderr)

Это просто и не должно включать ничего кроме sys.stderr.

15
Florian Castellane 8 Янв 2019 в 07:29

Никто не упомянул logging, но регистрация была создана специально для сообщения об ошибке Сообщения. По умолчанию он настроен на запись в stderr. Этот скрипт:

# foo.py
import logging
logging.basicConfig(format='%(message)s')

logging.warning('I print to stderr by default')
logging.info('For this you must change the level and add a handler.')
print('hello world')

Имеет следующий результат при запуске в командной строке:

$ python3 foo.py > bar.txt
I print to stderr by default

bar.txt содержит «привет мир»)

(Обратите внимание, что logging.warn был устарел, используйте logging.warning вместо)

116
cglacet 23 Дек 2019 в 14:59

print >> sys.stderr пропал в Python3. http://docs.python.org/3.0/whatsnew/3.0.html говорит :

Old: print >> sys.stderr, "fatal error"
New: print("fatal error", file=sys.stderr)

Для многих из нас кажется несколько неестественным откладывать пункт назначения до конца команды. Альтернатива

sys.stderr.write("fatal error\n")

Выглядит более объектно-ориентированным и элегантно переходит от общего к конкретному. Но обратите внимание, что write не является заменой 1: 1 для print.

162
Joachim W 9 Фев 2020 в 21:05

Для Python 2 мой выбор: print >> sys.stderr, 'spam' Потому что вы можете просто напечатать списки / дикты и т. Д. Без преобразования в строку. print >> sys.stderr, {'spam': 'spam'} вместо: sys.stderr.write(str({'spam': 'spam'}))

129
Frankovskyi Bogdan 5 Июл 2017 в 19:40

Я бы сказал, что ваш первый подход:

print >> sys.stderr, 'spam' 

Это "Один ... очевидный способ сделать это" Другие не удовлетворяют правилу № 1 ("Красиво лучше, чем некрасиво.")

30
Carl F. 7 Апр 2011 в 01:05

РЕДАКТИРОВАТЬ В заднем плане, я думаю, что возможная путаница с изменением sys.stderr и отсутствием обновленного поведения делает этот ответ не таким хорошим, как использование простой функции, как указывали другие.

Использование только частичного экономит вам 1 строку кода. Потенциальная путаница не стоит сохранять 1 строку кода.

оригинал

Чтобы сделать это еще проще, вот версия, которая использует «частичный», который является большой помощью в обертывании функций.

from __future__ import print_function
import sys
from functools import partial

error = partial(print, file=sys.stderr)

Вы тогда используете это так

error('An error occured!')

Вы можете проверить, что он печатает в stderr, а не в stdout, выполнив следующие действия (переопределение кода с http://coreygoldberg.blogspot.com.au/2009/05/python-redirect-or-turn-off-stdout-and.html) :

# over-ride stderr to prove that this function works.
class NullDevice():
    def write(self, s):
        pass
sys.stderr = NullDevice()

# we must import print error AFTER we've removed the null device because
# it has been assigned and will not be re-evaluated.
# assume error function is in print_error.py
from print_error import error

# no message should be printed
error("You won't see this error!")

Недостатком этого является частичное присваивание значения sys.stderr для обернутой функции во время создания. Это означает, что , если вы перенаправите stderr позже, это не повлияет на эту функцию. Если вы планируете перенаправить stderr, используйте метод ** kwargs, упомянутый aaguirre на этой странице.

16
Community 23 Май 2017 в 12:02

Ответ на вопрос: есть разные способы печати stderr в python, но это зависит от 1.) какую версию python мы используем 2.) какой именно вывод мы хотим.

Разница между print и функцией записи stderr: stderr : stderr (стандартная ошибка) - это канал, который встроен в каждую систему UNIX / Linux, когда ваша программа аварийно завершает работу и выводит отладочную информацию (например, трассировку в Python), она попадает в канал stderr.

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

Python2: если мы используем python2, то

>>> import sys
>>> print "hi"
hi
>>> print("hi")
hi
>>> print >> sys.stderr.write("hi")
hi

Завершающая запятая в Python2 в Python3 стала параметром, поэтому если мы используем запятые, чтобы избежать перехода на новую строку после печати, в Python3 это будет выглядеть как print ('Text to print', end = ''), что является синтаксической ошибкой в Python2 ,

http://python3porting.com/noconv.html

Если мы проверим тот же сценарий выше в Python 3:

>>> import sys
>>> print("hi")
hi

В Python 2.6 существует импорт future для печати в функция . Поэтому, чтобы избежать любых синтаксических ошибок и других различий, мы должен запускать любой файл, в котором мы используем print () из future import print_function . Импорт future работает только в Python 2.6 и позже, так что для Python 2.5 и ранее у вас есть два варианта. Вы можете либо конвертируйте более сложную печать во что-то более простое, или вы можете использовать отдельную функцию печати, которая работает как в Python2, так и Python3 .

>>> from __future__ import print_function
>>> 
>>> def printex(*args, **kwargs):
...     print(*args, file=sys.stderr, **kwargs)
... 
>>> printex("hii")
hii
>>>

Случай: Следует отметить, что sys.stderr.write () или sys.stdout.write () (stdout (стандартный вывод) - это канал, который встроен в каждую систему UNIX / Linux) не является заменой для печати, но да мы можем использовать его как альтернативу в некоторых случаях. Print - это оболочка, которая оборачивает ввод пробелом и символом новой строки в конце и использует функцию записи для записи. По этой причине sys.stderr.write () работает быстрее.

Не: , мы также можем отслеживать и отлаживать, используя ведение журнала.

#test.py
import logging
logging.info('This is the existing protocol.')
FORMAT = "%(asctime)-15s %(clientip)s %(user)-8s %(message)s"
logging.basicConfig(format=FORMAT)
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
logging.warning("Protocol problem: %s", "connection reset", extra=d)

https://docs.python.org/2/library/logging.html#logger-objects

-1
Vinay Kumar 30 Янв 2018 в 13:17

Если вы хотите выйти из программы из-за фатальной ошибки, используйте:

sys.exit("Your program caused a fatal error. ... description ...")

И import sys в заголовке.

0
feli_x 26 Ноя 2019 в 11:59