Reputation: 8315
I'm trying to use/write a custom Python logging handler. When I use it, logging appears for my main code, but not for a module it uses. I just can't figure how to get the logging for the module mylib
to appear and would welcome assistance. I'm sure I'm just doing something simple wrong in handling the handler.
The main code of the program is as follows (main.py):
import logging
import colorlogging
import mylib
def main():
global log
log = logging.getLogger(__name__)
log.addHandler(colorlogging.ColorisingStreamHandler())
log.setLevel(logging.DEBUG)
log.info('started main program')
mylib.do_something()
log.debug('main program debug message')
log.info('finished main program')
if __name__ == '__main__':
main()
The module used by the program is as follows (mylib.py):
import logging
log = logging.getLogger(__name__)
def do_something():
log.info('doing something')
log.debug('library debug message')
The handler code is as follows (colorlogging.py):
import ctypes
import logging
import os
class ColorisingStreamHandler(logging.StreamHandler):
# color names to indices
colorMap = {
'black': 0,
'red': 1,
'green': 2,
'yellow': 3,
'blue': 4,
'magenta': 5,
'cyan': 6,
'white': 7,
}
# level colour specifications
# syntax: logging.level: (background color, foreground color, bold)
levelMap = {
logging.DEBUG: (None, 'blue', False),
logging.INFO: (None, 'white', False),
logging.WARNING: (None, 'yellow', False),
logging.ERROR: (None, 'red', False),
logging.CRITICAL: ('red', 'white', True),
}
# control sequence introducer
CSI = '\x1b['
# normal colours
reset = '\x1b[0m'
def istty(self):
isatty = getattr(self.stream, 'isatty', None)
return isatty and isatty()
def emit(self, record):
try:
message = self.format(record)
stream = self.stream
if not self.istty:
stream.write(message)
else:
self.outputColorised(message)
stream.write(getattr(self, 'terminator', '\n'))
self.flush()
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)
def outputColorised(self, message):
self.stream.write(message)
def colorise(self, message, record):
if record.levelno in self.levelMap:
backgroundColor, \
foregroundColor, \
bold = self.levelMap[record.levelno]
parameters = []
if backgroundColor in self.colorMap:
parameters.append(str(self.colorMap[backgroundColor] + 40))
if foregroundColor in self.colorMap:
parameters.append(str(self.colorMap[foregroundColor] + 30))
if bold:
parameters.append('1')
if parameters:
message = ''.join((
self.CSI,
';'.join(parameters),
'm',
message,
self.reset
))
return message
def format(self, record):
message = logging.StreamHandler.format(self, record)
if self.istty:
# Do not colorise traceback.
parts = message.split('\n', 1)
parts[0] = self.colorise(parts[0], record)
message = '\n'.join(parts)
return message
Upvotes: 1
Views: 167
Reputation: 880537
Add the ColorisingStreamHandler
to the root logger so it will affect all child loggers which propagate the record.
main.py:
import logging
import colorlogging
import mylib
def main():
global log
log = logging.getLogger(__name__)
root = logging.root
root.addHandler(colorlogging.ColorisingStreamHandler())
root.setLevel(logging.DEBUG)
log.info('started main program')
mylib.do_something()
log.debug('main program debug message')
log.info('finished main program')
if __name__ == '__main__':
main()
yields
started main program (white)
doing something (white)
library debug message (blue)
main program debug message (blue)
finished main program (white)
Upvotes: 2