Skip to content

F-String Debugging

Python 3.8 introduced the = specifier for f-strings, allowing expressions to display both their source and value.

This feature simplifies debugging by eliminating the need to manually write variable names.

x = 42
print(f"{x=}")   # x=42

The output automatically includes the expression:

x=42

Basic Usage

The = specifier prints the expression and its evaluated value.

count = 100
name = "Bob"
active = True

print(f"{count=}")   # count=100
print(f"{name=}")    # name='Bob'
print(f"{active=}")  # active=True

Expressions

The debug specifier works with any Python expression, not only variables.

x = 5

print(f"{x + 10=}")       # x + 10=15
print(f"{x * 2=}")        # x * 2=10
print(f"{x ** 2=}")       # x ** 2=25

items = [1, 2, 3]
print(f"{len(items)=}")   # len(items)=3
print(f"{sum(items)=}")   # sum(items)=6

It also works with function calls and attributes:

def add(a, b):
    return a + b

print(f"{add(2,3)=}")   # add(2,3)=5
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

p = Point(3,4)
print(f"{p.x=}, {p.y=}")   # p.x=3, p.y=4

Combining with Format Specifiers

The = specifier can be combined with format specifiers.

value = 123.456789

print(f"{value=}")        # value=123.456789
print(f"{value=:.2f}")    # value=123.46
print(f"{value=:10.2f}")  # value=    123.46

Numeric formatting works as expected:

large = 1234567

print(f"{large=:,}")   # large=1,234,567
print(f"{large=:_}")   # large=1_234_567

Spaces Around =

Whitespace inside the f-string is preserved.

x = 42

print(f"{x=}")     # x=42
print(f"{x =}")    # x =42
print(f"{x= }")    # x= 42
print(f"{x = }")   # x = 42

This allows you to control readability.

a, b, c = 1, 2, 3

print(f"{a=},{b=},{c=}")        # compact
print(f"{a = }, {b = }, {c = }")  # readable

Practical Debugging Patterns

Inspect multiple variables

def calculate(a, b, c):
    result = (a + b) * c
    print(f"{a=}, {b=}, {c=}, {result=}")
    return result

Debug loops

items = ["apple", "banana", "cherry"]

for i, item in enumerate(items):
    print(f"{i=}, {item=}")

Debug intermediate values

def complex_function(x, y):
    print(f"ENTER: {x=}, {y=}")

    intermediate = x * y
    print(f"{intermediate=}")

    result = intermediate ** 2
    print(f"EXIT: {result=}")

    return result

String Representation

By default the debug specifier uses repr().

name = "Alice"

print(f"{name=}")    # name='Alice'

You can override this behavior:

print(f"{name=!s}")  # name=Alice
print(f"{name=!r}")  # name='Alice'

ASCII Representation

Use !a for ASCII-safe output.

text = "Héllo"

print(f"{text=}")    # text='Héllo'
print(f"{text=!a}")  # text='H\\xe9llo'

Limitations

The = specifier works only in f-strings.

x = 42

print(f"{x=}")   # works

It does not work with str.format():

fmt = "{x=}"
# fmt.format(x=42)  # does not produce debug output

Also note:

f"{x=}" requires Python 3.8+

Key Takeaways

  • The = specifier prints both an expression and its value.
  • It works with variables, expressions, function calls, and attributes.
  • Format specifiers can still be applied after =.
  • The output uses repr() by default.
  • !s, !r, and !a control string representation.
  • The feature is available only in Python 3.8+.
  • It provides a concise way to add debugging output.