简体   繁体   中英

how to get Python logging messages to appear for modules using custom handler

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

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM