Formatters in Logging Module Should Allow F-Strings

formatters:
simple:
# Sets the format for log messages, including timestamp, logger name, level, and message.
format: ‘%(asctime)s - %(name)s - %(levelname)s - %(message)s’

Why not allow

formatters:
fstring:
# Sets the format for log messages, including timestamp, logger name, level, and message.
format: ‘{asctime} - {name:10} - {levelname:8} - {message}’

That way string widths, padding etc can be used.

Notice the change from simple to fstring. That allows backward compatibility. Doesn’t break existing code.

If you have variables called asctime, name, levelname and message, that should work already?

The % support from logging is an old school feature. Applying % (asctime, name, levelname, message) to (or calling .format(...) on), the given string is predictable, and easy to implement.

But with f-strings, I doubt it’s a good idea to create a new special context/scope/closure thing, especially for logging call, in which those variables are inserted, just so that f-strings can bring them in.

Even if you’re still pushing for this, how should name clashes be handled (if any of the names asctime, name, levelname, message are defined in scope of the logging call - which one is displayed in the f-string)?

format: ‘%(asctime)s - %(name)s - %(levelname)s - %(message)s’

You can’t add widths for example here. You have to write a custom formatter.
What I see is almost everything of this type is now with fstrings which are a lot more flexible.

So what name clashes? ascttime, name, levelname message etc are all available for the fstring. Same as in the existing set up.

One to think about if someone’s visiting the source.

The logging module predates f-strings, so formatters were built in.

One to think about if someone’s visiting the source.

I don’t think it’s possible solely within logging. It fundamentally needs either changing the parser and therefore the language, to add a special case for logging calls and formatters. Or perhaps changing f-strings in all Python to ignore NameErrors in their fields, and let them be used as templates, e.g. with .format.

Does the style="{" keyword do what you want here? You can use the str.format syntax, using keywords for the names of the variables you need.

There is some nuance in that logging messages are lazily formatted, the arguments aren’t computed unless the log is actually emitted. So it’s not exactly an f-string, but the formatting can be similar.

Example:

import logging

logger = logging.getLogger()
h = logging.StreamHandler()
h.setFormatter(logging.Formatter(fmt="{asctime} - {name:10} - {levelname:8} - {message}", style="{"))
logger.addHandler(h)
logger.setLevel(logging.INFO)
logger.info("hi")
2025-01-10 17:34:08,351 - root       - INFO     - hi

The main difference is that I can’t do something like {levelname.lower()} as I could with an f-string.

You can, actually. It’s the same kind of format string used with the % operator:

>>> print("%(name)10s - %(pi)07.2f" % {"name": "foo", "pi": 3.14159})
       foo - 0003.14