The Python Oracle

PyLint message: logging-format-interpolation

This video explains
PyLint message: logging-format-interpolation

--

Become part of the top 3% of the developers by applying to Toptal
https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzle Game 3 Looping

--

Chapters
00:00 Question
01:02 Accepted answer (Score 339)
02:05 Answer 2 (Score 74)
03:53 Answer 3 (Score 35)
04:27 Answer 4 (Score 0)
05:37 Thank you

--

Full question
https://stackoverflow.com/questions/3461...

Accepted answer links:
[Optimization]: https://docs.python.org/howto/logging.ht...

Answer 2 links:
[time differences]: https://github.com/PyCQA/pylint/issues/2...
[related issue and comment]: https://github.com/PyCQA/pylint/issues/1...
[2.4]: http://pylint.pycqa.org/en/latest/whatsn...
[2.5]: http://pylint.pycqa.org/en/latest/whatsn...
[PEP-0498]: https://www.python.org/dev/peps/pep-0498

Answer 2 links:
[time differences]: https://github.com/PyCQA/pylint/issues/2...
[related issue and comment]: https://github.com/PyCQA/pylint/issues/1...
[2.4]: http://pylint.pycqa.org/en/latest/whatsn...
[2.5]: http://pylint.pycqa.org/en/latest/whatsn...
[PEP-0498]: https://www.python.org/dev/peps/pep-0498

Answer 2 links:
[time differences]: https://github.com/PyCQA/pylint/issues/2...
[related issue and comment]: https://github.com/PyCQA/pylint/issues/1...
[2.4]: http://pylint.pycqa.org/en/latest/whatsn...
[2.5]: http://pylint.pycqa.org/en/latest/whatsn...
[PEP-0498]: https://www.python.org/dev/peps/pep-0498

Answer 2 links:
[time differences]: https://github.com/PyCQA/pylint/issues/2...
[related issue and comment]: https://github.com/PyCQA/pylint/issues/1...
[2.4]: http://pylint.pycqa.org/en/latest/whatsn...
[2.5]: http://pylint.pycqa.org/en/latest/whatsn...
[PEP-0498]: https://www.python.org/dev/peps/pep-0498

Answer 2 links:
[time differences]: https://github.com/PyCQA/pylint/issues/2...
[related issue and comment]: https://github.com/PyCQA/pylint/issues/1...
[2.4]: http://pylint.pycqa.org/en/latest/whatsn...
[2.5]: http://pylint.pycqa.org/en/latest/whatsn...
[PEP-0498]: https://www.python.org/dev/peps/pep-0498

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #python3.x #pylint



ACCEPTED ANSWER

Score 427


It is not true for logger statement because it relies on former "%" format like string to provide lazy interpolation of this string using extra arguments given to the logger call. For instance instead of doing:

logger.error('oops caused by %s' % exc)

you should do

logger.error('oops caused by %s', exc)

so the string will only be interpolated if the message is actually emitted.

You can't benefit of this functionality when using .format().


Per the Optimization section of the logging docs:

Formatting of message arguments is deferred until it cannot be avoided. However, computing the arguments passed to the logging method can also be expensive, and you may want to avoid doing it if the logger will just throw away your event.




ANSWER 2

Score 97


Maybe this time differences can help you.

Following description is not the answer for your question, but it can help people.

If you want to use fstrings (Literal String Interpolation) for logging, then you can disable it from .pylintrc file with disable=logging-fstring-interpolation, see: related issue and comment.

Also you can disable logging-format-interpolation.


For pylint 2.4:

There are 3 options for logging style in the .pylintrc file: old, new, fstr

fstr option added in 2.4 and removed in 2.5

Description from .pylintrc file (v2.4):

[LOGGING]

# Format style used to check logging format string. `old` means using %
# formatting, `new` is for `{}` formatting,and `fstr` is for f-strings.
logging-format-style=old

for old (logging-format-style=old):

foo = "bar"
self.logger.info("foo: %s", foo)

for new (logging-format-style=new):

foo = "bar"
self.logger.info("foo: {}", foo)
# OR
self.logger.info("foo: {foo}", foo=foo)

Note: you can not use .format() even if you select new option.

pylint still gives the same warning for this code:

self.logger.info("foo: {}".format(foo))  # W1202
# OR
self.logger.info("foo: {foo}".format(foo=foo))  # W1202

for fstr (logging-format-style=fstr):

foo = "bar"
self.logger.info(f"foo: {foo}")

Personally, I prefer fstr option because of PEP-0498.




ANSWER 3

Score 39


In my experience a more compelling reason than optimization (for most use cases) for the lazy interpolation is that it plays nicely with log aggregators like Sentry.

Consider a 'user logged in' log message. If you interpolate the user into the format string, you have as many distinct log messages as there are users. If you use lazy interpolation like this, the log aggregator can more reasonably interpret this as the same log message with a bunch of different instances.




ANSWER 4

Score 12


Here is an example of why it's better to use %s instead of f-strings in logging.

>>> import logging
>>> logging.basicConfig(level=logging.INFO)
>>> logger = logging.getLogger('MyLogger')
>>>
>>> class MyClass:
...     def __init__(self, name: str) -> None:
...         self._name = name
...     def __str__(self) -> str:
...         print('GENERATING STRING')
...         return self._name
...
>>> c = MyClass('foo')
>>> logger.debug('Created: %s', c)
>>> logger.debug(f'Created: {c}')
GENERATING STRING

Inspired by Python 3.7 logging: f-strings vs %.