Proper indentation for multiline strings?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Indenting multiline strings in Python is not just a style issue. The leading spaces inside the triple-quoted literal become part of the string unless you remove them deliberately. The right formatting depends on whether you want the string to preserve indentation exactly or whether you only want the code itself to stay readable.
Triple-Quoted Strings Preserve Whitespace
Python triple-quoted strings keep embedded newlines and leading spaces exactly as written.
Because the indentation is inside the string literal, the resulting value contains those spaces. That is often surprising when the code is nested inside a function or class definition.
The Most Common Fix: textwrap.dedent
If you want nicely indented source code without keeping the indentation in the final string, use textwrap.dedent.
This is the standard answer for multiline text embedded in indented code blocks.
Why the extra strip()? Triple-quoted strings often include a leading newline because the opening quotes sit on their own line. strip() removes that outer whitespace when you do not want it.
When Exact Indentation Is the Point
Sometimes preserving whitespace is correct. For example, if you are generating Python code, YAML, or a formatted text block where indentation has meaning, you may want the literal spaces.
In that case, do not dedent blindly. The spaces are part of the data.
The main question is not "how should I indent multiline strings?" It is "should this string preserve indentation, or should the code indentation be ignored?"
Parenthesized Concatenation Is Often Cleaner
If you do not actually need embedded line breaks in the resulting string, implicit string concatenation inside parentheses is often cleaner than triple quotes.
This keeps the code readable without introducing unintended indentation or newlines.
It is especially good for:
- SQL fragments
- long error messages
- URLs or command templates
where the final string should be one line.
Building Lines Explicitly
Another readable pattern is to build the final text from a list of lines and join them.
This approach works well when the content is structured and you want complete control over blank lines.
Docstrings Are a Special Case
Docstrings are multiline strings too, but they usually follow documentation conventions rather than generic text-formatting rules. Tools that inspect docstrings may normalize indentation, and developers often use helper utilities such as inspect.cleandoc when they need cleaned output.
This is a reminder that not all multiline strings are consumed the same way.
A Practical Style Rule
Use one of these patterns based on the actual output shape:
- triple quotes plus
dedentwhen you want a readable multiline literal without extra indentation - raw triple quotes when whitespace should be preserved exactly
- parenthesized adjacent strings when the final result should be one line
- list-of-lines plus
joinwhen the structure is assembled programmatically
Trying to force one style onto every use case usually produces awkward strings or awkward code.
Common Pitfalls
- Forgetting that indentation inside triple quotes becomes part of the string value.
- Leaving an unwanted leading newline because the opening triple quotes were placed on their own line.
- Using triple quotes for single-line output where parenthesized concatenation would be cleaner.
- Applying
dedentto text where indentation is semantically meaningful. - Debugging alignment issues without checking
repr, which reveals the actual spaces and newline characters.
Summary
- Triple-quoted strings preserve leading spaces and newlines exactly as written.
- Use
textwrap.dedentwhen you want readable source indentation but clean output text. - Use parenthesized adjacent strings when the final output should stay on one line.
- Preserve indentation only when it is part of the data, not just an artifact of code layout.
- Check
reprwhen multiline string whitespace is behaving differently than expected.

