Maintaining Logging And/or Stdout/stderr In Python Daemon
Solution 1:
I use the python-daemon library for my daemonization behavior.
Interface described here:
Implementation here:
It allows specifying a files_preserve argument, to indicate any file descriptors that should not be closed when daemonizing.
If you need logging via the sameHandler instances before and after daemonizing, you can:
- First set up your logging Handlers using
basicConfigordictConfigor whatever. - Log stuff
- Determine what file descriptors your
Handlers depend on. Unfortunately this is dependent on theHandlersubclass. If your first-installedHandleris aStreamHandler, it's the value oflogging.root.handlers[0].stream.fileno(); if your second-installedHandleris aSyslogHandler, you want the value oflogging.root.handlers[1].socket.fileno(); etc. This is messy :-( - Daemonize your process by creating a
DaemonContextwithfiles_preserveequal to a list of the file descriptors you determined in step 3. - Continue logging; your log files should not have been closed during the double-fork.
An alternative might be, as @Exelian suggested, to actually use different Handler instances before and after the daemonziation. Immediately after daemonizing, destroy the existing handlers (by deling them from logger.root.handlers?) and create identical new ones; you can't just re-call basicConfig because of the issue that @dave-mankoff pointed out.
Solution 2:
You can simplify the code for this if you set up your logging handler objects separately from your root logger object, and then add the handler objects as an independent step rather than doing it all at one time. The following should work for you.
import daemon
importlogginglogger= logging.getLogger()
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler("./foo.log")
logger.addHandler(fh)
context = daemon.DaemonContext(
files_preserve = [
fh.stream,
],
)
logger.debug( "Before daemonizing." )
context.open()
logger.debug( "After daemonizing." )
Solution 3:
We just had a similar issue, and due to some things beyond my control, the daemon stuff was separate from the stuff creating the logger. However, logger has a .handlers and .parent attributes that make it possible with something like:
self.files_preserve = self.getLogFileHandles(self.data.logger)
defgetLogFileHandles(self,logger):
""" Get a list of filehandle numbers from logger
to be handed to DaemonContext.files_preserve
"""
handles = []
for handler in logger.handlers:
handles.append(handler.stream.fileno())
if logger.parent:
handles += self.getLogFileHandles(logger.parent)
return handles
Post a Comment for "Maintaining Logging And/or Stdout/stderr In Python Daemon"