Skip to main content Brad's PyNotes

Textwrap Module: Elegant Text Formatting and Wrapping

TL;DR

The textwrap module provides functions for formatting text blocks with intelligent line wrapping, indentation control, and paragraph formatting - perfect for creating clean output, documentation, and user interfaces.

Interesting!

Textwrap can intelligently handle word boundaries and hyphenation, and includes a powerful dedent() function that automatically removes common leading whitespace - incredibly useful for cleaning up triple-quoted strings in code.

Basic Text Wrapping

wrap() - Split Text into Lines

python code snippet start

import textwrap

long_text = "This is a very long line of text that needs to be wrapped to fit within a specific width for better readability and formatting."

# Split into list of lines
lines = textwrap.wrap(long_text, width=50)
for line in lines:
    print(f"'{line}'")

# Output:
# 'This is a very long line of text that needs to be'
# 'wrapped to fit within a specific width for better'
# 'readability and formatting.'

python code snippet end

fill() - Create Formatted Paragraph

python code snippet start

# Return as single string with newlines
formatted = textwrap.fill(long_text, width=50)
print(formatted)

# Same output but as one string with \n characters

python code snippet end

Text Indentation Control

dedent() - Remove Common Indentation

python code snippet start

# Perfect for cleaning up triple-quoted strings
def example_function():
    help_text = textwrap.dedent("""
        Usage: myprogram [options]
        
        Options:
            -h, --help     Show this help
            -v, --verbose  Enable verbose mode
            -o, --output   Output file
        """)
    return help_text.strip()

print(example_function())
# Clean output without extra indentation!

python code snippet end

indent() - Add Prefix to Lines

python code snippet start

code_block = """def hello():
    print("Hello, world!")
    return True"""

# Add comment-style prefix
commented = textwrap.indent(code_block, '# ')
print(commented)

# Output:
# # def hello():
# #     print("Hello, world!")
# #     return True

# Add markdown code block formatting
markdown = textwrap.indent(code_block, '    ')
print(markdown)

python code snippet end

Custom Line Filtering

python code snippet start

# Only indent non-empty lines
text = "Line 1\n\nLine 3\nLine 4"
indented = textwrap.indent(text, '>>> ', predicate=lambda line: line.strip())
print(indented)

# Output:
# >>> Line 1
# 
# >>> Line 3
# >>> Line 4

python code snippet end

Advanced Formatting with TextWrapper

Bullet Lists and Hanging Indents

python code snippet start

from textwrap import TextWrapper

wrapper = TextWrapper(
    width=60,
    initial_indent='• ',      # First line prefix
    subsequent_indent='  ',   # Continuation lines
    break_long_words=False
)

items = [
    "First item with a long description that will wrap across multiple lines",
    "Second item that also has quite a bit of text to demonstrate the formatting",
    "Third and final item in our example list"
]

for item in items:
    print(wrapper.fill(item))
    print()  # Empty line between items

python code snippet end

Documentation Formatting

python code snippet start

def format_docstring(text: str, width: int = 72) -> str:
    """Format docstring with proper indentation"""
    # Clean up the input
    cleaned = textwrap.dedent(text).strip()
    
    # Wrap with hanging indent for parameters
    wrapper = TextWrapper(
        width=width,
        initial_indent='    ',
        subsequent_indent='        ',
        break_long_words=False
    )
    
    return wrapper.fill(cleaned)

docstring = """
    This function performs complex calculations with multiple parameters and returns detailed results.
    """

print(format_docstring(docstring))

python code snippet end

Practical Applications

CLI Help Text Generator

python code snippet start

class HelpFormatter:
    def __init__(self, width: int = 80):
        self.width = width
        self.option_wrapper = TextWrapper(
            width=width - 20,
            initial_indent=' ' * 20,
            subsequent_indent=' ' * 20
        )
    
    def format_option(self, short: str, long: str, description: str) -> str:
        # Format option flags
        flags = f"  {short}, {long}".ljust(18)
        
        # Wrap description
        wrapped_desc = self.option_wrapper.fill(description)
        
        # Combine, removing initial indent from first line
        return flags + wrapped_desc[20:]
    
    def format_help(self, options: list) -> str:
        help_lines = ["Options:"]
        for short, long, desc in options:
            help_lines.append(self.format_option(short, long, desc))
        return '\n'.join(help_lines)

# Usage
help_formatter = HelpFormatter()
options = [
    ('-h', '--help', 'Show this help message and exit'),
    ('-v', '--verbose', 'Enable verbose output with detailed logging and progress information'),
    ('-o', '--output', 'Specify the output file path for saving results')
]

print(help_formatter.format_help(options))

python code snippet end

Code Comment Formatter

python code snippet start

def format_comment_block(text: str, width: int = 70) -> str:
    """Format text as a comment block"""
    # Clean and wrap text
    cleaned = textwrap.dedent(text).strip()
    lines = textwrap.wrap(cleaned, width=width - 4)  # Account for comment chars
    
    # Add comment formatting
    if not lines:
        return ''
    
    result = ['/*']
    for line in lines:
        result.append(f' * {line}')
    result.append(' */')
    
    return '\n'.join(result)

comment = """
    This is a long comment that explains the complex algorithm used below.
    It should be properly formatted with appropriate line breaks.
    """

print(format_comment_block(comment))

python code snippet end

Email/Message Formatting

python code snippet start

def format_email_quote(original_message: str, width: int = 72) -> str:
    """Format text as email quote with > prefix"""
    # Preserve paragraph breaks
    paragraphs = original_message.strip().split('\n\n')
    
    quoted_paragraphs = []
    for paragraph in paragraphs:
        # Clean and wrap each paragraph
        cleaned = ' '.join(paragraph.split())  # Remove extra whitespace
        wrapped = textwrap.fill(cleaned, width=width - 2)  # Account for '> '
        quoted = textwrap.indent(wrapped, '> ')
        quoted_paragraphs.append(quoted)
    
    return '\n>\n'.join(quoted_paragraphs)

original = """
Thanks for your email about the project status.

I wanted to follow up on the discussion we had yesterday regarding the implementation timeline and resource allocation for the upcoming release.

Let me know if you need any additional information.
"""

print(format_email_quote(original))

python code snippet end

Text Shortening

shorten() for Truncation

python code snippet start

# Intelligent text shortening
long_title = "This is an extremely long title that needs to be shortened for display purposes"

short_title = textwrap.shorten(long_title, width=50, placeholder='...')
print(short_title)
# Output: "This is an extremely long title that needs..."

# Custom placeholder
short_custom = textwrap.shorten(long_title, width=50, placeholder=' [more]')
print(short_custom)
# Output: "This is an extremely long title that [more]"

python code snippet end

Textwrap is essential for creating professional-looking text output in Python applications! Use textwrap with argparse for CLI help formatting and string methods for text processing . Perfect for log message formatting and works seamlessly with pathlib for documentation generation .

Reference: Python Textwrap Documentation