Python 3.7 logging: f-strings vs % [duplicate]
I'm running into a performance problem in a project, and I narrowed it down to some of the log lines. It seems that f-strings are calculated even when my logging facility is above the level of the line that is logging.
Consider this example to demonstrate the issue:
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(f'Created: {c}')
When this example is run, I get "GENERATING STRING" printed to screen, indicating that the __str__
method is being ran even though my logging level is set to INFO
and the log line is for DEBUG
.
From what I can tell today, the solution is to use the following vs an f-string.
logger.debug('Created: %s', c)
There are three things going through my head right now.
- Most of the examples and docs I read seem to be pretty old.
- This project is Python 3.7+ only (not worried about being backwards compatible).
- I have a lot of lines of code to update.
I'm curious to know what others do in this situation. Is the %s
the best (most modern) approach? Is there a more modern way that I should be logging as demonstrated above?
I have a lot of code to update (fix), and I'm hoping to align with modern best practices.
The documentation says that the logging lib is optimized to use the %s
formatting style. I can't remember where it is mentionned exactly, but I read it a few months ago.
Edit - Found! https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles
Edit2 - (thanks to Robin Nemeth): https://docs.python.org/3/howto/logging.html#optimization
IMO, using %s
in your strings is NOT the most modern approach. Definitely, most developers will prefer to use f-strings because it is more convenient and easy to read (and write).
But, you interestingly find a specific case where you may not want to use an f-string. If you need to avoid automatic call of __str__()
method because of optimisation issue, then it is probably a good enough reason to use %s
instead of f-strings. But, this could also indicate that something may be done in your program to reduce the complexity of __str__()
. Most of the time it shouldn't take so much time or resources to calculate a string representation for an object...