ChatGPT解决这个技术问题 Extra ChatGPT

PyLint message: logging-format-interpolation

For the following code:

logger.debug('message: {}'.format('test'))

pylint produces the following warning:

logging-format-interpolation (W1202): Use % formatting in logging functions and pass the % parameters as arguments Used when a logging statement has a call form of “logging.(format_string.format(format_args...))”. Such calls should use % formatting instead, but leave interpolation to the logging function by passing the parameters as arguments.

I know I can turn off this warning, but I'd like to understand it. I assumed using format() is the preferred way to print out statements in Python 3. Why is this not true for logger statements?


A
Asclepius

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.


@pfnuesel, .format() is expanded before the call to logger.error, while "lazy interpolation" means expansion is done only if needed (eg the message is actually displayed somewhere)
Is there a good reference for this lazy evaluation being preferred and making a difference? I couldn't find one in PEP282 or the logging library
But does this just mean that we will have maintenance problems with our code later? Will we later be "recommended" by pylint to move to the .format() style at some point because logging has upgraded? I ask because I'm more interested in maintainability than I am in bleeding-edge speed performance, at least for most tasks.
@MikeWilliamson : I think this message is a warning because there are possible side effects, but you can safely ignore it.
While much of the motivation behind the warning is around performance (ie: if a log statement is not emitted, then the interpolation cost is saved), it's worth noting that in many (arguably most) applications the performance cost is negligible. See: github.com/PyCQA/pylint/issues/2395 and github.com/PyCQA/pylint/issues/2354
m
mustafagok

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.


you can add "python.linting.pylintArgs": ["--logging-format-style=old"] to the vscode/settings.json file. docs
in pylint 2.3.1: optparse.OptionValueError: option logging-format-style: invalid value: 'fstr', should be in ['old', 'new'] upgrading to latest pylint (2.4.4) fixed this.
I am having following error: Try installing a more recent version of python-pylint, and please open a bug report if the issue persists in t\ he latest release. Thanks!
update: the fstr logging format option was removed, set disable=logging-fstring-interpolation instead in .pylintrc. github.com/PyCQA/pylint/issues/3570
A shorter use of f strings is self.logger.info(f"{foo=}"). No need to spell out the variable or expression twice.
T
Tristan Crockett

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.


yes, this is the strongest argument for the lazy logging arguments formatting
p
pelos

Might be several years after but having to deal with this the other day, I made simple; just formatted the string before logger.

message = 'message: {}'.format('test')
logger.debug(message)

That way there was no need to change any of the settings from log, if later on desire to change to a normal print there is no need to change the formatting or code.


The answer from Tristan Crockett is the best reason NOT to use your method, even if it seems more practical at first.
Solve the question about how to remove the warning. is the logger that is not capable of parse and join the string properly. and should be keep in mind that the programmer who needs set what he wants to log.