Как печатать на stderr в Python?
Есть несколько способов написать в 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 †, так в чем же разница и есть ли какие-либо преимущества или недостатки в том или ином случае? Какой способ следует использовать?
† Должен быть один - и желательно только один - очевидный способ сделать это.
Ответы
Ответ 1
Я обнаружил, что это единственный короткий + гибкий + портативный + читаемый:
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
Ответ 2
import sys
sys.stderr.write()
Это мой выбор, просто более читаемый и точно говорящий о том, что вы собираетесь делать, и переносимый между версиями.
Изменение: "pythonic" - это третья мысль о читабельности и производительности... с учетом этих двух вещей, с python 80% вашего кода будет pythonic. понимание списка - это "большая вещь", которая используется не так часто (удобочитаемость).
Ответ 3
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
.
Ответ 4
Для Python 2 мой выбор:
print >> sys.stderr, 'spam'
Потому что вы можете просто распечатать списки /dicts и т.д., Не преобразовывая их в строку.
print >> sys.stderr, {'spam': 'spam'}
вместо:
sys.stderr.write(str({'spam': 'spam'}))
Ответ 5
Никто еще не упоминал 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
)
Ответ 6
Я бы сказал, что ваш первый подход:
print >> sys.stderr, 'spam'
- это "Один... очевидный способ сделать это". Другие не удовлетворяют правилу № 1 ( "Красиво лучше, чем уродливое" ).
Ответ 7
Я использовал следующее: 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")
Ответ 8
Это будет имитировать стандартную функцию печати, но выводить на stderr
def print_err(*args):
sys.stderr.write(' '.join(map(str,args)) + '\n')
Ответ 9
РЕДАКТИРОВАТЬ В ретроспективе, я думаю, что потенциальная путаница с изменением 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 на этой странице.
Ответ 10
В 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
.
Ответ 11
То же самое относится к stdout:
print 'spam'
sys.stdout.write('spam\n')
Как указано в других ответах, печать предлагает довольно удобный интерфейс, который часто более удобен (например, для печати информации отладки), в то время как запись выполняется быстрее, а также может быть более удобной, когда вам нужно форматировать вывод точно определенным образом. Я бы подумал о ремонтопригодности:
-
Вы можете позже решить переключиться между stdout/stderr и обычным файлом.
Синтаксис -
print() изменился в Python 3, поэтому, если вам нужно поддерживать обе версии, write() может быть лучше.
Ответ 12
Я работаю на python 3.4.3. Я вырезаю небольшую типизацию, которая показывает, как я здесь:
[18:19 [email protected] pexpect]$ python3
>>> import sys
>>> print("testing", file=sys.stderr)
testing
>>>
[18:19 [email protected] pexpect]$
Это сработало? Попробуйте перенаправить stderr в файл и посмотреть, что произойдет:
[18:22 [email protected] pexpect]$ python3 2> /tmp/test.txt
>>> import sys
>>> print("testing", file=sys.stderr)
>>> [18:22 [email protected] pexpect]$
[18:22 [email protected] 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 [email protected] pexpect]$
Ну, кроме того, что небольшое введение, которое дает вам python, было прорвано в stderr (где еще он будет идти?), он работает.
Ответ 13
Если вы выполните простой тест:
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 раз быстрее!
Ответ 14
Пытаться:
from sys import stderr
print >> sys.stderr, 'spam'
Ответ 15
Ответ на вопрос: есть разные способы печати 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
Если мы проверим тот же сценарий выше в python3:
>>> import sys
>>> print("hi")
hi
В Python 2.6 есть возможность импорта в функцию в будущем. Поэтому, чтобы избежать любых синтаксических ошибок и других различий, мы должны начать любой файл, в котором мы используем print(), из будущего импорта print_function. Будущий импорт работает только в 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() работает быстрее.
Примечание: мы также можем отследить и отладить, используя Logging
#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
Ответ 16
import logging
logging.basicConfig(format='[%(levelname)s] %(message)s')
logging.error('is error, alarm!')
logging.warning('is simple waring')
print('hello')
ведение журнала pydoc