El módulo textwrap de la biblioteca estándar formatea párrafos para terminales, informes, logs, mensajes, documentación e interfaces basadas en texto. Ajusta líneas a un ancho, añade sangrías, acorta textos por palabras y elimina el margen común de cadenas multilínea. Así evita funciones manuales frágiles y centraliza las reglas de presentación.
Esta guía explica wrap(), fill(), shorten(), dedent(), indent() y TextWrapper, incluyendo Unicode, palabras largas, guiones, párrafos y rendimiento.
Dividir un párrafo con wrap
wrap() recibe un único párrafo y devuelve una lista de líneas sin saltos finales.
import textwrap
texto = "Python permite crear herramientas claras para automatizar tareas repetitivas."
lineas = textwrap.wrap(texto, width=24)
print(lineas)El ancho se mide en caracteres de Python, no en píxeles ni columnas visuales reales. Emojis, marcas combinantes y caracteres asiáticos pueden ocupar un espacio distinto en pantalla.
Crear una cadena lista con fill
fill() equivale a unir el resultado de wrap() con saltos de línea. Es la opción más cómoda para imprimir o guardar un párrafo.
formateado = textwrap.fill(texto, width=40)
print(formateado)Ambas funciones aceptan las mismas opciones: sangrías, tratamiento de palabras largas, guiones, espacios, número máximo de líneas y placeholder.
Sangría inicial y colgante
initial_indent se aplica a la primera línea. subsequent_indent se aplica a las demás y cuenta dentro del ancho.
salida = textwrap.fill(
texto,
width=44,
initial_indent="* ",
subsequent_indent=" ",
)
print(salida)Este patrón funciona bien en listas, ayudas de CLI, correo en texto plano e informes. Elige la anchura considerando el prefijo.
Acortar por palabras
shorten() primero colapsa todos los espacios y después elimina palabras del final hasta que el texto y el placeholder quepan.
resumen = textwrap.shorten(
"Una descripción muy larga para una tarjeta pequeña",
width=32,
placeholder="...",
)
print(resumen)La función evita cortar arbitrariamente dentro de palabras normales. El placeholder debe caber. Si necesitas conservar espacios originales, aplica otra política.
Eliminar la sangría común con dedent
Las cadenas triples dentro de funciones heredan la sangría del código. dedent() elimina el margen común y conserva la estructura relativa.
def mensaje():
texto = """
Hola,
este elemento sigue sangrado.
Hasta pronto.
"""
return textwrap.dedent(texto).strip()Tabs y espacios son whitespace, pero no equivalen como sangría. Mezclarlos puede impedir el resultado esperado. Python 3.14 mejoró la normalización de líneas vacías que contienen otros caracteres de espacio.
Añadir prefijos con indent
indent() añade un prefijo a las líneas no vacías por defecto. Un predicado opcional controla cuáles lo reciben.
bloque = "primera\n\nsegunda"
print(textwrap.indent(bloque, "> "))
todas = textwrap.indent(bloque, "+ ", lambda linea: True)Es útil para citas, logs, comentarios, mensajes reenviados y bloques de código. El predicado recibe la línea con su terminador cuando existe.
Palabras mayores que el ancho
Por defecto, break_long_words=True permite dividir un token largo para respetar la anchura. Esto puede ser malo para URLs, hashes, identificadores y comandos.
salida = textwrap.fill(
"identificador_extremadamente_largo_sin_espacios",
width=20,
break_long_words=False,
)
print(salida)Si la división está desactivada, una línea puede superar el ancho. Decide si importa más conservar el token o el diseño.
Comportamiento con guiones
break_on_hyphens=True permite preferir saltos después de guiones. El comportamiento sigue convenciones orientadas al inglés y puede no ser adecuado para todos los idiomas o identificadores técnicos.
Para tokens indivisibles, establece break_on_hyphens=False y break_long_words=False.
Tabs y otros espacios
expand_tabs=True expande tabs usando tabsize. Después, replace_whitespace=True sustituye tab, newline, tab vertical, form feed y carriage return por espacios simples.
Si desactivas el reemplazo, los saltos internos pueden producir resultados extraños. Divide el contenido en párrafos antes de ajustarlo.
Un párrafo por vez
wrap() y fill() están diseñados para un único párrafo. Separa documentos largos y conserva explícitamente las líneas vacías.
def formatear_documento(texto, ancho=70):
bloques = texto.split("\n\n")
return "\n\n".join(
textwrap.fill(bloque, width=ancho)
for bloque in bloques
if bloque.strip()
)Documentos con listas, títulos, tablas o bloques de código requieren un parser más estructurado.
Limitar el número de líneas
max_lines y placeholder crean vistas previas compactas.
vista = textwrap.fill(
texto_largo,
width=50,
max_lines=2,
placeholder=" [...]",
)El placeholder participa en el cálculo. Prueba anchuras pequeñas y traducciones, porque un texto localizado más largo puede no caber.
Reutilizar TextWrapper
Las funciones de conveniencia crean una instancia en cada llamada. Reutiliza TextWrapper cuando formatees muchos textos con la misma configuración.
wrapper = textwrap.TextWrapper(
width=60,
subsequent_indent=" ",
break_long_words=False,
)
for parrafo in parrafos:
print(wrapper.fill(parrafo))La instancia es mutable. Evita compartirla entre threads si las opciones cambian durante el uso. Una configuración fija por worker es más sencilla.
Unicode y anchura visual
textwrap cuenta caracteres de la cadena. Los terminales pueden mostrar caracteres CJK en dos columnas, acentos combinantes sin columna adicional y secuencias de emoji como un único símbolo visible.
Cuando necesites alineación visual exacta, combina una biblioteca de ancho de terminal con la política de ajuste. No supongas que len() equivale a columnas.
HTML y Markdown
Ajustar HTML o Markdown sin analizar puede dividir etiquetas, enlaces, tablas y fences de código. Usa un parser o procesa solo nodos de texto conocidos.
En navegador, el diseño depende de CSS y del ancho disponible. Una cantidad fija de caracteres no sustituye un layout responsive.
Ejemplo: ayuda de línea de comandos
def ayuda(titulo, descripcion):
cabecera = textwrap.dedent(f"""
{titulo}
{'=' * len(titulo)}
""").strip()
cuerpo = textwrap.fill(
descripcion,
width=72,
initial_indent=" ",
subsequent_indent=" ",
break_long_words=False,
)
return f"{cabecera}\n{cuerpo}"El ejemplo separa la estructura de la cabecera y el párrafo, y conserva identificadores largos.
Errores frecuentes
- Pasar varios párrafos como uno solo.
- Esperar anchura visual exacta para cualquier Unicode.
- Dividir URLs e identificadores sin querer.
- Mezclar tabs y espacios antes de
dedent(). - Esperar que
shorten()conserve espacios. - Compartir un wrapper mutable entre threads.
- Formatear HTML o Markdown como texto plano.
Buenas prácticas
- Elige el ancho para una superficie concreta.
- Formatea párrafos por separado.
- Conserva tokens largos cuando sea necesario.
- Prueba placeholders traducidos.
- Usa
dedent().strip()en cadenas triples. - Reutiliza
TextWrapperen lotes grandes. - Separa formato textual de diseño visual.
Guías relacionadas
Continúa con difflib en Python, locale en Python, pydoc en Python, fileinput en Python y linecache en Python.
Consulta la documentación oficial de textwrap y la documentación de strings.
Conclusión
textwrap ofrece una API completa para presentar texto en entornos con ancho limitado. Su uso correcto exige separar párrafos, definir una política para tokens largos y entender que el número de caracteres no siempre coincide con la anchura visual.







