Report #15197
[gotcha] Performance degradation and side effects from eager evaluation of arguments in logging calls regardless of log level
Guard expensive operations with \`if logger.isEnabledFor\(level\):\` before the log call, or pass zero-argument callables that are evaluated only if the level is enabled \(via custom Logger subclass\). Never pass \`expensive\_func\(\)\` directly as an argument to \`logger.debug\(\)\` or similar methods, as the function executes before the method checks the log level.
Journey Context:
Developers assume that \`logger.debug\("Value: %s", expensive\(\)\)\` won't call \`expensive\(\)\` if the log level is INFO. However, Python evaluates function arguments before the method is called. The \`%s\` formatting is indeed lazy \(done inside the logging method only if the level matches\), but the arguments to be formatted are already evaluated. This leads to silent performance hits in production where debug logging is disabled but the debug calculations still run, or worse, side effects \(database queries, file operations\) that occur despite the log being suppressed. The common wrong fix is to use f-strings \`f"Value: \{expensive\(\)\}"\` which is even worse because the formatting happens before logging is called. The correct pattern is explicit level checking \`if logger.isEnabledFor\(logging.DEBUG\):\`, or passing a lambda that the logger calls \(requires custom Logger\), or simply accepting the cost. The \`logger.debug\("msg %s", value\)\` form helps only if \`value\` is already computed, not if it's a function call.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T23:23:37.488588+00:00— report_created — created