Как перенаправить stdout и stderr в logger в Python

У меня есть журнал, у которого есть RotatingFileHandler . Я хочу перенаправить все Stdout и Stderr в регистратор. Как это сделать?

5 Solutions collect form web for “Как перенаправить stdout и stderr в logger в Python”

Недостаточно комментариев для комментариев, но я хотел добавить версию этого, которая сработала для меня, если другие находятся в аналогичной ситуации.

 class LoggerWriter: def __init__(self, level): # self.level is really like using log.debug(message) # at least in my case self.level = level def write(self, message): # if statement reduces the amount of newlines that are # printed to the logger if message != '\n': self.level(message) def flush(self): # create a flush method so things can be flushed when # the system wants to. Not sure if simply 'printing' # sys.stderr is the correct way to do it, but it seemed # to work properly for me. self.level(sys.stderr) 

и это будет выглядеть примерно так:

 log = logging.getLogger('foobar') sys.stdout = LoggerWriter(log.debug) sys.stderr = LoggerWriter(log.warning) 

Если это полностью Python-система (т.е. нет библиотек C, которые пишут fds напрямую, как об этом спрашивал Ignacio Vazquez-Abrams), тогда вы можете использовать подход, предложенный здесь :

 class LoggerWriter: def __init__(self, logger, level): self.logger = logger self.level = level def write(self, message): if message != '\n': self.logger.log(self.level, message) 

а затем установите sys.stdout и sys.stderr в экземпляры LoggerWriter .

Кажется, что все предыдущие ответы имеют проблемы с добавлением дополнительных строк, где они не нужны. Решение, которое наилучшим образом подходит для меня, – это http://www.electricmonk.nl/log/2011/08/14/redirect-stdout-and-stderr-to-a-logger-in-python/ , где он демонстрирует, как отправьте как stdout, так и stderr в регистратор:

 import logging import sys class StreamToLogger(object): """ Fake file-like stream object that redirects writes to a logger instance. """ def __init__(self, logger, log_level=logging.INFO): self.logger = logger self.log_level = log_level self.linebuf = '' def write(self, buf): for line in buf.rstrip().splitlines(): self.logger.log(self.log_level, line.rstrip()) logging.basicConfig( level=logging.DEBUG, format='%(asctime)s:%(levelname)s:%(name)s:%(message)s', filename="out.log", filemode='a' ) stdout_logger = logging.getLogger('STDOUT') sl = StreamToLogger(stdout_logger, logging.INFO) sys.stdout = sl stderr_logger = logging.getLogger('STDERR') sl = StreamToLogger(stderr_logger, logging.ERROR) sys.stderr = sl print "Test to standard out" raise Exception('Test to standard error') 

Результат выглядит так:

 2011-08-14 14:46:20,573:INFO:STDOUT:Test to standard out 2011-08-14 14:46:20,573:ERROR:STDERR:Traceback (most recent call last): 2011-08-14 14:46:20,574:ERROR:STDERR: File "redirect.py", line 33, in 2011-08-14 14:46:20,574:ERROR:STDERR:raise Exception('Test to standard error') 2011-08-14 14:46:20,574:ERROR:STDERR:Exception 2011-08-14 14:46:20,574:ERROR:STDERR:: 2011-08-14 14:46:20,574:ERROR:STDERR:Test to standard error 

Обратите внимание, что self.linebuf = '' – это то, где обрабатывается флеш, а не реализация функции флеша.

Вы можете использовать диспетчер контекстов redirect_stdout:

 import logging from contextlib import redirect_stdout logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) logging.write = lambda msg: logging.info(msg) if msg != '\n' else None with redirect_stdout(logging): print('Test') 

или как это

 import logging from contextlib import redirect_stdout logger = logging.getLogger('Meow') logger.setLevel(logging.INFO) formatter = logging.Formatter( fmt='[{name}] {asctime} {levelname}: {message}', datefmt='%m/%d/%Y %H:%M:%S', style='{' ) ch = logging.StreamHandler() ch.setLevel(logging.INFO) ch.setFormatter(formatter) logger.addHandler(ch) logger.write = lambda msg: logger.info(msg) if msg != '\n' else None with redirect_stdout(logger): print('Test') 

С добавлением флеша к ответу Винай Саджипа:

 class LoggerWriter: def __init__(self, logger, level): self.logger = logger self.level = level def write(self, message): if message != '\n': self.logger.log(self.level, message) def flush(self): pass 
  • Python: получить выход из командной строки, которая выходит с ненулевым кодом выхода
  • Линейная буферизация stdout не выполняется на MINGW / MSYS Python 2.7.3
  • Python считывает из подпроцесса stdout и stderr отдельно при сохранении порядка
  • ловить stdout в реальном времени из подпроцесса
  • Временно перенаправить stdout / stderr
  • Внедрение стандартного вывода другой программы для небуферизации с использованием Python
  • запись функции pytest для проверки вывода на консоли (stdout) в python?
  • Как проверить распечатки?
  • Ошибка ввода / вывода IOError при печати
  • Запретить печать строки python
  • python: неблокирующий подпроцесс, check stdout
  • Python - лучший язык программирования в мире.