Text Wrapping & Formatting (textwrap)

The textwrap module reflows plain text to a chosen line width and tidies indentation, turning a long run-on string into neat, readable lines.

Learn Text Wrapping & Formatting (textwrap) in our free Python course — an interactive lesson with runnable examples, a practice exercise and a quick reference.

Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Whenever you print to a terminal, build a help message, or format an email, textwrap gives you wrapping, indenting, dedenting, and clean truncation in a single line of code.

textwrap.fill(text, width=N) breaks text into lines no longer than N characters and returns one ready-to-print string. textwrap.wrap does the same but hands back a list of lines:

indent(text, prefix) adds a prefix to the start of each non-blank line — great for quoting or block-marking. dedent(text) does the reverse: it removes the common leading whitespace shared by every line, perfect for triple-quoted strings:

dedent only removes the indentation that all lines share, so any deeper, relative indentation inside the block is kept intact.

shorten(text, width) truncates on a word boundary and adds a placeholder so the result fits — ideal for previews. And initial_indent / subsequent_indent give you bullet-style "hanging" indents where wrapped lines align under the first:

Replace each ___ with the right textwrap function so the message wraps to width 20 and each line is quoted with "| " .

✅ Use fill for a string, or join the list yourself

❌ dedent does nothing because indentation isn't shared

✅ Make sure every line shares the indent (a leading newline helps)

❌ Using a width too small for shorten's placeholder

✅ Leave room for the placeholder (default " [...]" is 6 chars)

Take a long message, wrap it to width 30, then quote every line with "# " to make a tidy comment-style notice block.

Lesson complete — your output looks polished!

You can reflow text with fill and wrap , prefix lines with indent , clean up triple-quoted blocks with dedent , truncate cleanly with shorten , and build hanging indents with initial_indent and subsequent_indent .

🚀 Up next: benchmarking with timeit — measure which approach is actually faster.

Practice quiz

What does textwrap.fill return?

  • A list of line strings
  • The number of lines
  • One wrapped string with newlines, ready to print
  • A TextWrapper object

Answer: One wrapped string with newlines, ready to print. fill returns a single string with newlines inserted — it's just ' '.join(wrap(...)).

What does textwrap.wrap return?

  • A list of separate line strings
  • A single wrapped string
  • A dictionary of lines
  • None

Answer: A list of separate line strings. wrap returns a list of lines, handy when you want to count or process each line individually.

How is fill related to wrap?

  • They are unrelated
  • wrap is fill.split()
  • fill ignores the width argument
  • fill is ' '.join(wrap(...))

Answer: fill is ' '.join(wrap(...)). fill is exactly ' '.join(wrap(...)) — same wrapping work, but it returns a printable string.

What does textwrap.indent(text, prefix) do?

  • Removes leading whitespace
  • Adds the prefix to the start of each non-blank line
  • Wraps text to a width
  • Truncates text

Answer: Adds the prefix to the start of each non-blank line. indent prepends the given prefix (e.g. '> ') to every non-blank line, great for quoting blocks.

What does textwrap.dedent remove?

  • The common leading whitespace shared by every line
  • All whitespace
  • Trailing whitespace only
  • Blank lines

Answer: The common leading whitespace shared by every line. dedent strips only the indentation that ALL lines share, preserving any deeper relative indentation.

What does textwrap.shorten do that simple slicing does not?

  • It pads the text to the width
  • It reverses the text
  • It truncates on a word boundary and adds a placeholder
  • It encodes the text to bytes

Answer: It truncates on a word boundary and adds a placeholder. shorten collapses whitespace, truncates at a word boundary, and appends a placeholder (default ' [...]').

What is the default placeholder used by textwrap.shorten?

  • '...'

The default placeholder is ' [...]', six characters long, so the width must leave room for it.

What raises a ValueError in textwrap.shorten?

  • Passing a list instead of a string
  • Using a width over 1000
  • Omitting the width
  • A width too small to fit even the placeholder

Answer: A width too small to fit even the placeholder. If width is too small for the placeholder, shorten raises 'placeholder too large for max width'.

What do initial_indent and subsequent_indent create together?

  • A centered block
  • A hanging indent where wrapped lines align under the first
  • Double-spaced text
  • A numbered list automatically

Answer: A hanging indent where wrapped lines align under the first. initial_indent prefixes the first line and subsequent_indent the rest, producing bullet-style hanging indents.

Why might dedent appear to do nothing on a string?

  • The string is too long
  • dedent only works on bytes
  • Not all lines share a common leading indentation
  • The width was not set

Answer: Not all lines share a common leading indentation. dedent removes only shared indentation; if one line (e.g. the first) has no leading spaces, nothing is common to strip.