4 ms·
A wart is the standard logging module, which uses %-style strings. For example: log.debug("Unexpected, got %r", (got,)) By doing it this way, it can defer ren
by stubish 6y ago
A wart is the standard logging module, which uses %-style strings. For example:
log.debug("Unexpected, got %r", (got,))
By doing it this way, it can defer rendering the string until it is actually needed, which is (assumed to be) a win when the logging module is normally just going to toss the low level messages away rather than emit them anywhere.
I think you lose this optimization if you use f-strings. I don't think rendering of the string can be lazy, deferred until actually needed.
- shakna 6y agoWhilst percent strings can't, calls to format can. So: log.debug("Unexpected, got {got}".format(got=got)) Or, to just use the available locals to automatically fill that in for you: log.debug("Unexepected, got {got}".format(**locals())) Or if you want both globals and locals with a preference for locals: log.debug("Unexepected, got {got}".format(**{**globals(), **locals()}))
- jon_richards 6y agoYes, I was asked by a Junior if they should always use f strings now. There are still a couple situations where you need format, such as when you’re formatting a variable instead of a literal. Also, shoutout to Template for untrusted strings. It’s surprisingly unknown. Most people suggest replace or a custom format function.
- ploxiln 6y agoAlso, remember that the first argument to the logging functions is considered to be a format string. So using f-strings is not just less efficient, it is also not robust, unless you do: logging.debug("%s", f"Unexpected, got {got}") because otherwise, if the format string is the first/only argument, and `got` unexpectedly contain `%`, an exception will be raised due to a missing format parameter. (Also, for the logging functions, you don't pass a tuple, just a normal series of arguments.)
- altncatchfire 6y agoI dont think this is true. I just tried with the following program and it runs as expected (Run on Python 3.7.9). import logging got = "%d" logging.warning(f"hi {got}") logging.debug(f"hi {got}") Output WARNING:root:hi %d DEBUG:root:hi %d
- dagenix 6y agoAs the sibling comment points out, it actually doesn't work that way. The first parameter is only treated as a format string _if_ there are arguments. If not, it is treated as a literal string: https://github.com/python/cpython/blob/dcea78ff53d02733ac5983255610b651aa1c0034/Lib/logging/__init__.py#L363 https://github.com/python/cpython/blob/dcea78ff53d02733ac598...
- whoopdedo 6y agologging.Formatter defaults to working with %-style strings but it it can be configured to use the {}-style of str.format. (As of 3.2) You still miss out on the scoping of f-strings, and embedding function calls. But passing around what amounts to an "eval" expression is a footgun that should obviously be frowned upon. There's also an option for $-style Template strings. But I can't recall when I've ever seen someone use that.
- ploxiln 6y ago> In Python 3.2, the Formatter gained a style keyword parameter which, while defaulting to % for backward compatibility, allowed the specification of { or $ to support the formatting approaches supported by str.format() and string.Template. Note that this governs the formatting of logging messages for final output to logs, and is completely orthogonal to how an individual logging message is constructed. The style option only applies to the outer format applied by the formatter (timestamp, level, file, line, etc), it does not apply to the logging calls.
- pansa2 6y agoEven if logging can't use f-strings, is there a reason it can't use `string.format`? Limiting logging to `%`-formatting seems to be an inconsistency similar to supporting `%` but not `format` on `bytes` and `bytearray`.
- joshuamorton 6y ago> Even if logging can't use f-strings, is there a reason it can't use `string.format`? the logging module predates the `.format` function.