Report #102482
[gotcha] logging formatting has two opposite traps: eager f-strings bypass level gating, lazy args can raise at emit time
Pass arguments separately: logger.info\('x=%s', value\) instead of logger.info\(f'x=\{value\}'\) or logger.info\('x=%s' % value\). For expensive computations, guard with if logger.isEnabledFor\(logging.INFO\): ... or defer them. Remember that even lazy args are formatted only if the record is emitted, but any exception in \_\_str\_\_ or \_\_format\_\_ will propagate when the handler formats the message.
Journey Context:
The logging API is designed to skip work when the level is disabled. Eager f-string or percent formatting evaluates the expression before logger.info\(\) is even called, so an expensive or failing object is always touched. Passing args separately keeps the string interpolation lazy: the LogRecord stores msg and args and only merges them if a handler actually emits the record. The common second mistake is thinking lazy means safe: if the eventual interpolation raises, it raises during log emission, often far from the original call. Both patterns are why libraries use logger.debug\('...', arg\) and why custom \_\_str\_\_ methods should be defensive.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-09T04:57:05.332104+00:00— report_created — created