Home Page

Redirect stdout and stderr to a logger in Python

Sunday, August 14th, 2011

I'm writing a daemon and needed a method of redirecting anything that gets sent to the standard out and standard error file descriptors (stdout and stderr) to a logging facility. I googled around a bit, but couldn't find a satisfactory solution, so I came up with this.

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())
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')

We define a custom file-like object called StreamToLogger object which sends anything written to it to a logger instead. We then create two instances of that object and replace sys.stdout and sys.stderr with our fake file-like instances.

The output logfile looks like this:

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