21

The Python logging tutorial says that the newer ways of formatting are beyond the scope of the tutorial, without mentioning where to learn about it.

I would appreciate any examples or link to documentation that allow me to use .format() style message formatting in logging calls such as debug(), info(), etc.

vvvvv
  • 25,404
  • 19
  • 49
  • 81
Terrence Brannon
  • 4,760
  • 7
  • 42
  • 61
  • 5
    The question and answer are out-of-date and link to Python 2 documentation. The most modern string-formatting approach (f-strings since Python 3.6) work nicely with logging calls, e.g. `logging.debug(f'var = {var}')`. The [latest documentation](https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles) covers the approach with `BraceMessage`. – nealmcb Apr 15 '20 at 04:13
  • Note also that pylint can be configured to achieve consistency in logging. If you use f-strings, as suggested e.g. by `pzelnip` at [f-strings advantages for logging; performance](https://github.com/PyCQA/pylint/issues/2354#issuecomment-414526879), then in `.pylintrc` you might want `disable=logging-fstring-interpolation,` – nealmcb Aug 09 '20 at 21:53

3 Answers3

16

Recently, I was looking for that too. I think I got pointed to the solution here on SO, but I only have the final url at hand. This is what I do:

# http://plumberjack.blogspot.de/2010/10/supporting-alternative-formatting.html
class BraceMessage(object):
    def __init__(self, fmt, *args, **kwargs):
        self.fmt = fmt
        self.args = args
        self.kwargs = kwargs

    def __str__(self):
        return self.fmt.format(*self.args, **self.kwargs)

_F = BraceMessage

Can be used like this:

logger.debug(_F("foo {0} {quux}", bar, quux=baz))

The formatting will only take place in the very moment the message is evaluated, so you don't lose lots of performance if a log level is disabled. The author of that snippet above made this (and some other utilities) available as a package: logutils.

Jonas Schäfer
  • 20,140
  • 5
  • 55
  • 69
  • 4
    Why not just call it `F` or `L`? Don't need to use two characters when one is sufficient. The leading underscore is supposed to indicate a private attribute. – Asclepius Dec 08 '20 at 16:21
0

You can use the following code to enable using format style in python 3.2+

import logging

class BracketStyleRecord(logging.LogRecord):
    def getMessage(self):
        msg = str(self.msg) # see logging cookbook
        if self.args:
            try:
                msg = msg % self.args # retro-compability for 3rd party code
            except TypeError: # not all arguments converted during formatting
                msg = msg.format(*self.args)
        return msg

logging.setLogRecordFactory(BracketStyleRecord)
logging.basicConfig()
logging.error("The first number is %s", 1) # old-style
logging.error("The first number is {}", 1) # new-style

For details, caveats and references see this answer.

loopbackbee
  • 21,962
  • 10
  • 62
  • 97
0

When it comes to logging format Pylint can also be named as a source. See Pylint logging-format-interpolation W1202.

  • %s formatting is preferred over "{}".format("foo")
  • f-string is also reasonable (adaption of Pylint config needed)
Ken Jiiii
  • 474
  • 9
  • 21