Python logging

From wikinotes

Logging is like levelled/filterable printing.

Documentation

basicconfig docs https://docs.python.org/3/library/logging.html#logging.basicConfig
logrecord attributes https://docs.python.org/3/library/logging.html#logrecord-attributes

Usage

# quickly configure log output
logging.basicConfig(level=logging.DEBUG,
                    format='[%(asctime)s] %(levelname)-8s: %(message)s)',
                    datefmt='%Y/%m/%d %H:%M')
# create logger object on each module
logger = logging.getLogger(__name__)

logger.debug('debug')
logger.info('info')
logger.warning('warning')
logger.error('error')
logger.critical('critical')

Complex Logging

Most of the time, logging.basicConfig is all you need.

If you need more power, the logging framework is composed of simple and powerful objects that allow you to tailor it to your use case. (ex: maybe you want to log debug to a file, and only warning stdout).

Objects:

  • logger: the interface communicated with
  • handler: controls where log is output (stderr, file, ...)
  • filter: filters are attached to handlers. They filter which messages are visible.
  • formatter: string formatting for logs (add time, namespace, etc)


Filters

python logs are hierarchical. The loglevel/format for A is inherited by A.B and so on.

Filters are inherited by child loggers.

  • a specific Logger (perhaps you want to filter passwords) (ex: logging.getLogger('A.B') )
  • a specific Handler (perhaps you want to silence a very chatty module) (ex: logging.StreamHandler() )

example filter

class FilterChattyModule(logging.Filter):
    def filter(self, record):
        if record.name.startswith('chatty'):
            return 0
        return 1

install filter using logging.basicConfig()

logging.basicConfig()
for handler in logging.root.handlers:
    handler.addFilter(FilterChattyModule())

install filter in manual setup

logfilter = logging.Formatter('[%(asctime)s] %(levelname)-8s: %(message)s)')

loghandler = logging.StreamHandler()
loghandler.setFormat(logformat)
loghandler.addFilter(logfilter)

logging.root.addHandler(loghandler)
logging.root.setLevel(logging.DEBUG)

Special Environments

IPython

IPython already has a logger configured, to change the loglevel it is easiest to customize the root logger.

logging.root.level = logging.DEBUG

Autodesk Maya

Maya's script-editor uses the loghandler of type maya.utils.MayaGuiLogHandler. If you want to change the loglevel, you will need to customize it.

for loghandler in logging.root.handlers:
    if isinstance(loghandler, maya.utils.MayaGuiLogHandler):
        loghandler.setLevel(logging.DEBUG)