The textwrap module formats text for display. Wrap long lines, indent blocks, and clean up whitespace.

wrap and fill

import textwrap
 
text = "This is a very long line that needs to be wrapped to fit within a certain width for better readability."
 
# wrap: returns list of lines
lines = textwrap.wrap(text, width=40)
print(lines)
# ['This is a very long line that needs to',
#  'be wrapped to fit within a certain',
#  'width for better readability.']
 
# fill: returns single string with newlines
wrapped = textwrap.fill(text, width=40)
print(wrapped)
# This is a very long line that needs to
# be wrapped to fit within a certain
# width for better readability.

dedent: Remove Common Indentation

import textwrap
 
code = """
    def hello():
        print("Hello")
        return True
"""
 
# Remove common leading whitespace
cleaned = textwrap.dedent(code)
print(cleaned)
# 
# def hello():
#     print("Hello")
#     return True

Perfect for multiline strings in code:

def get_sql():
    return textwrap.dedent("""
        SELECT name, email
        FROM users
        WHERE active = true
        ORDER BY name
    """).strip()

indent: Add Indentation

import textwrap
 
text = """Line one
Line two
Line three"""
 
# Add prefix to all lines
indented = textwrap.indent(text, "  ")
print(indented)
#   Line one
#   Line two
#   Line three
 
# Add prefix conditionally
def not_empty(line):
    return line.strip() != ""
 
indented = textwrap.indent(text, "> ", predicate=not_empty)

shorten: Truncate with Ellipsis

import textwrap
 
text = "This is a long description that needs to be shortened for display."
 
short = textwrap.shorten(text, width=30)
print(short)  # "This is a long description [...]"
 
# Custom placeholder
short = textwrap.shorten(text, width=30, placeholder="...")
print(short)  # "This is a long description..."

TextWrapper Class

For repeated operations with same settings:

import textwrap
 
wrapper = textwrap.TextWrapper(
    width=50,
    initial_indent="• ",      # First line prefix
    subsequent_indent="  ",   # Other lines prefix
    break_long_words=False,   # Don't break words
    break_on_hyphens=True,    # Break on hyphens
)
 
text = "This is a bullet point that explains something important and needs multiple lines."
print(wrapper.fill(text))
# • This is a bullet point that explains
#   something important and needs multiple
#   lines.

Practical Examples

CLI Help Text

import textwrap
 
def print_help(commands: dict[str, str], width=60):
    for cmd, desc in commands.items():
        # Wrap description, indent continuation lines
        lines = textwrap.wrap(desc, width=width-20)
        print(f"  {cmd:<15} {lines[0]}")
        for line in lines[1:]:
            print(f"  {'':<15} {line}")
 
commands = {
    "init": "Initialize a new project in the current directory with default configuration.",
    "build": "Build the project for production deployment.",
    "test": "Run the test suite with coverage reporting enabled.",
}
print_help(commands)

Code Comments

import textwrap
 
def format_docstring(text: str, indent: int = 4) -> str:
    """Format text as a docstring."""
    lines = textwrap.wrap(text, width=72 - indent)
    indented = textwrap.indent("\n".join(lines), " " * indent)
    return f'"""\n{indented}\n{" " * indent}"""'

Log Messages

import textwrap
 
def log_message(level: str, message: str, width=80):
    prefix = f"[{level}] "
    wrapper = textwrap.TextWrapper(
        width=width,
        initial_indent=prefix,
        subsequent_indent=" " * len(prefix),
    )
    print(wrapper.fill(message))
 
log_message("ERROR", "Connection to database failed after 3 retries. The server may be down or the connection string may be incorrect.")
# [ERROR] Connection to database failed after 3 retries. The
#         server may be down or the connection string may be
#         incorrect.

Email Formatting

import textwrap
 
def format_email_body(paragraphs: list[str], width=72) -> str:
    wrapped = []
    for p in paragraphs:
        wrapped.append(textwrap.fill(p, width=width))
    return "\n\n".join(wrapped)

Quote Formatting

import textwrap
 
def format_quote(text: str, author: str, width=60) -> str:
    wrapped = textwrap.fill(text, width=width-2)
    quoted = textwrap.indent(wrapped, "> ")
    return f"{quoted}\n> \n> — {author}"
 
print(format_quote(
    "The only way to do great work is to love what you do.",
    "Steve Jobs"
))
# > The only way to do great work is to love what
# > you do.
# > 
# > — Steve Jobs

Quick Reference

import textwrap
 
# Wrap to list of lines
textwrap.wrap(text, width=70)
 
# Wrap to single string
textwrap.fill(text, width=70)
 
# Remove common indentation
textwrap.dedent(text)
 
# Add indentation
textwrap.indent(text, prefix)
 
# Truncate with ellipsis
textwrap.shorten(text, width, placeholder="[...]")
 
# Reusable wrapper
wrapper = textwrap.TextWrapper(
    width=70,
    initial_indent="",
    subsequent_indent="",
    expand_tabs=True,
    tabsize=8,
    replace_whitespace=True,
    drop_whitespace=True,
    break_long_words=True,
    break_on_hyphens=True,
)
FunctionPurpose
wrap()Split into list of lines
fill()Wrap into single string
dedent()Remove common leading whitespace
indent()Add prefix to lines
shorten()Truncate to width with ellipsis

textwrap handles the tedious parts of text formatting so your output looks clean.

React to this post: