Getting a more useful 'logging' module error output in python

python, python-3.x

Solution

Was just about to post this when Unutbu beat me to it. But here it is anyway:

You could try subclassing whichever handler you're using (example below using StreamHandler) and overiding the format method with a function that wraps it in a try: block

import traceback, logging

class MyStreamHandler(logging.StreamHandler):
    def format(self, record):
        try:
            return logging.StreamHandler.format(self, record)
        except TypeError:
            # Print a stack trace that includes the original log call
            traceback.print_stack() 


if __name__ == "__main__":
    log = logging.getLogger("testlogger")
    handler = MyStreamHandler()

    log.addHandler(handler)

    log.error("Try interpolating an int correctly: %i", 1)

    log.error("Now try passing a string to an int: %d", 'abc')

    log.error("And then a string to a string %s", 'abc')

gives me:

Try interpolating an int correctly: 1
  File "logtest2.py", line 19, in ?
    log.error("Now try passing a string to an int: %d", 'abc')
  File "/usr/lib64/python2.4/logging/__init__.py", line 999, in error
    apply(self._log, (ERROR, msg, args), kwargs)
  File "/usr/lib64/python2.4/logging/__init__.py", line 1079, in _log
    self.handle(record)
  File "/usr/lib64/python2.4/logging/__init__.py", line 1089, in handle
    self.callHandlers(record)
  File "/usr/lib64/python2.4/logging/__init__.py", line 1126, in callHandlers
    hdlr.handle(record)
  File "/usr/lib64/python2.4/logging/__init__.py", line 642, in handle
    self.emit(record)
  File "/usr/lib64/python2.4/logging/__init__.py", line 731, in emit
    msg = self.format(record)
  File "logtest2.py", line 8, in format
    traceback.print_stack()
None
And then a string to a string abc

I wouldn't leave this in any production code, but it should help you find things like

log.error("%d", 'a string')

Problem

I am using the `logger` module of python (python version 3.x, but it should not matter) and I noticed that an error in a format string is reported as such: ``` Traceback (most recent call last): File "/usr/lib/python3.1/logging/__init__.py", line 770, in emit msg = self.format(record) File "/usr/lib/python3.1/logging/__init__.py", line 650, in format return fmt.format(record) File "/usr/lib/python3.1/logging/__init__.py", line 438, in format record.message = record.getMessage() File "/usr/lib/python3.1/logging/__init__.py", line 308, in getMessage msg = msg % self.args TypeError: %d format: a number is required, not str ``` As you can see, there is no mention of where the actual error (in my code) was. By the way, here's what was wrong in my code: ``` logging.debug('This is a string %d', str(foo)) ``` Changing the `%d` in `%s` solved the problem. My question is: how do I get some slightly more useful information from the `logging` module output? Do I have to write my own logger? Where do I tweak the `logger` module?

Original source