Python Logging Formatting Best Practices | Generated by AI

Home 2026.04

Question: How does Python logging work, and is {0} formatting needed or better than using , or + string concatenation?

Answer:

Python’s built-in logging module is designed for flexible, efficient, and configurable logging, especially in production systems.


1. How Python logging works (core idea)

At a high level:

Example:

import logging

logging.basicConfig(level=logging.INFO)

logging.info("Hello world")

2. The key point: string formatting in logging

This is where your question matters.

logging.info("User %s logged in", username)
logging.info(f"User {username} logged in")
logging.info("User " + username + " logged in")
logging.info("User {} logged in".format(username))

3. Why %s (comma style) is better

🔥 Reason 1: Lazy evaluation (performance)

Logging only formats the string if the log level is enabled.

logging.debug("Expensive: %s", compute_heavy())

If level is INFO, this will NOT call formatting → saves CPU.

But this:

logging.debug(f"Expensive: {compute_heavy()}")

👉 compute_heavy() is executed every time, even if not logged.


🔥 Reason 2: cleaner separation

logging.info("User %s has %d points", user, points)

4. What about {0} or {}?

That comes from str.format():

"User {0}".format(username)

or

"User {}".format(username)

❗ In logging, this is NOT special

Logging does NOT use {} formatting by default.

So this:

logging.info("User {}", username)   # ❌ WRONG

Will NOT work.


5. Comparison summary

Style Example Recommended? Reason
% (logging style) "User %s", username ✅ YES Lazy, efficient
f-string f"User {username}" ❌ NO (for logging) Always evaluates
+ concat "User " + username ❌ NO Ugly + eager
.format() "User {}".format(username) ❌ NO Eager

6. Advanced: if you really want {} style

You can configure logging to use {} formatting:

logging.basicConfig(
    format="{asctime} - {message}",
    style="{"
)

But even then:

logging.info("User {}", username)  # still ❌

Because argument substitution still uses % internally.


7. Best practice (production-level)

Always write logs like this:

logging.debug("Processing file %s size=%d", filename, size)

NOT:

logging.debug(f"Processing file {filename} size={size}")

8. Simple mental model

Think of logging like:

“I give you a template + data, you decide later whether to build the string.”

That’s why %s + , is the correct design.


Final takeaway


If you want, I can show how this affects performance in a real benchmark (it’s surprisingly significant in high-throughput systems).


Back Donate