Как печатать на stderr в Python?

Я столкнулся с тремя способами печати на stderr:

import sys print >> sys.stderr, 'spam' sys.stderr.write('spam\n') from __future__ import print_function print('spam', file=sys.stderr) 

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

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

    12 Solutions collect form web for “Как печатать на stderr в Python?”

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

     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 

    sys.stderr.write() – мой выбор, просто более читаемый и точно говорящий о том, что вы намереваетесь сделать и переносите в разных версиях.

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

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

    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 .

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

     print >> sys.stderr, 'spam' 

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

    Я сделал следующее, используя 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") 

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

     def print_err(*args): sys.stderr.write(' '.join(map(str,args)) + '\n') 

    РЕДАКТИРОВКА В предидущем я думаю, что потенциальная путаница с изменением 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 на этой странице.

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

     # foo.py import logging logging.basicConfig(format='%(message)s') logging.warn('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 содержит «мир привет»)

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

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

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

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

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

    Я работаю в 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 (где еще это могло бы пойти?), Это работает.

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

     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 раза быстрее!

    Python - лучший язык программирования в мире.