How textwrap.dedent Strips Whitespace in Python
Python's textwrap.dedent() function provides a clean,
automated way to remove unwanted leading indentation from multiline
strings, such as docstrings or embedded templates. This article explains
the internal mechanics of textwrap.dedent(), how it
identifies the common indentation level across lines, and how it strips
that uniform whitespace while maintaining relative formatting.
The Multiline Indentation Problem
When defining multiline strings inside indented blocks such as functions, classes, or conditional statements, the string typically inherits the indentation of the surrounding code:
def generate_message():
message = """
Hello, World!
This is an indented string.
This line has extra indentation.
"""
return messagePrinting message directly preserves all the leading
spaces on each line, which often breaks formatting requirements for
terminal output, emails, or generated files.
How textwrap.dedent()
Works
The textwrap.dedent() function standardizes this
behavior by locating and stripping the shared "margin" from the
multiline text. The process follows three distinct steps:
- Splits the String into Lines: The function processes the string line by line.
- Calculates the Minimum Common Prefix: It examines all non-empty lines (lines containing at least one non-whitespace character) to find the longest sequence of leading whitespace characters shared by every line. Lines consisting entirely of whitespace are ignored during this calculation to prevent a blank line from resetting the common indentation to zero.
- Removes the Common Prefix: It removes that exact character sequence from the start of every line in the string. Any extra indentation beyond that common prefix remains untouched.
Example
import textwrap
sample = """
First line.
Second line.
Nested line.
"""
cleaned = textwrap.dedent(sample)
print(repr(cleaned))Output:
'\nFirst line.\nSecond line.\n Nested line.\n'
In this example, the minimum common indentation was four spaces. The
function stripped four spaces from each line, leaving
First line. and Second line. flush to the
left, while Nested line. preserved its two relative levels
of indentation (four remaining spaces).
Important Nuances
Character-Level Matching (Tabs vs. Spaces)
textwrap.dedent() treats tabs and spaces as distinct
characters. It does not expand tabs into spaces before calculating the
common prefix. If some lines use four spaces and others use a single tab
character, dedent() will only remove the whitespace prefix
that strictly matches character-for-character across all lines. To
prevent unexpected results, ensure consistent indentation or call
str.expandtabs() before dedenting.
The First Line Trap
A common pitfall occurs when placing text immediately after the opening triple quotes:
sample = """First line.
Second line.
Third line."""Because the first line has zero leading spaces, the common whitespace
prefix across all lines is an empty string. As a result,
dedent() will not remove any indentation from the
subsequent lines. To ensure proper dedenting, start multiline strings
with a newline right after the opening quotes.