Aprenda todo lo que puede hacer con Python textwrap módulo, que incluye formato, ajuste de texto, recorte y más
Python tiene muchas opciones para formatear cadenas y texto, incluidas cadenas f, format() función, plantillas y más. Sin embargo, hay un módulo que pocas personas conocen y se llama textwrap.
Este módulo está diseñado específicamente para ayudarlo con el ajuste de líneas, la sangría, el recorte y más, y en este artículo veremos todas las cosas para las que puede usarlo.
Comencemos con una función muy simple pero muy útil del textwrap módulo, llamado shorten:
from textwrap import shortenshorten("This is a long text or sentence.", width=10)
# 'This [...]'
shorten("This is a long text or sentence.", width=15)
# 'This is a [...]'
shorten("This is a long text or sentence.", width=15, placeholder=" <...>")
# 'This is a <...>'
Como el nombre sugiere, shorten nos permite recortar el texto a cierta longitud ( width) si la cadena especificada es demasiado larga. De forma predeterminada, el marcador de posición para el texto recortado es [...]pero eso se puede anular con el placeholder argumento.
Una función más interesante de este módulo es wrap. El caso de uso obvio es dividir texto largo en líneas de la misma longitud, pero hay más cosas que podemos hacer con él:
from textwrap import wrap
s = '1234567890'
wrap(s, 3)
# ['123', '456', '789', '0']
En este ejemplo dividimos una cadena en partes iguales que pueden ser útiles para el procesamiento por lotes, en lugar de simplemente formatear.
Sin embargo, el uso de esta función tiene algunas advertencias:
s = '12\n3 45678\t9\n0'
wrap(s, 3)
# ['12', '3 ', '456', '78', '9 0']
# the first ("12") element "includes" newline
# the 4th element ("78") "includes" tab
wrap(s, 3, drop_whitespace=False, tabsize=1)
# ['12 ', '3 ', '456', '78 ', '9 0']
Debes tener cuidado con los espacios en blanco cuando utilices wrap – arriba puedes ver el comportamiento con caracteres de nueva línea, tabulación y espacio. Puedes ver que el primer elemento ( 12) “incluye” nueva línea y cuarto elemento ( 78) “incluye” pestaña, sin embargo, estos se eliminan de forma predeterminada, por lo tanto, estos elementos solo tienen 2 caracteres en lugar de 3.
Podemos especificar el drop_whitespace argumento de palabra clave para preservarlos y mantener la longitud adecuada de los fragmentos.
Puede que sea obvio, pero wrap También es excelente para reformatear archivos completos con un cierto ancho de línea:
with open("some-text.md", "r", encoding="utf-8") as f:
formatted = wrap(f.read(), width=80) # List of lines
formatted = fill(f.read(), width=80) # Single string that includes line breaks
# ... write it back
También podemos utilizar el fill función que es una abreviatura de "\n".join(wrap(text, ...)). La diferencia entre los 2 es que wrap nos dará una lista de líneas que necesitaríamos para concatenarnos, y fill nos da una sola cadena que ya está unida mediante nuevas líneas.
textwrap El módulo también incluye una versión más potente. wrap función, que es una TextWrapper clase:
import textwrapw = textwrap.TextWrapper(width=120, placeholder=" <...>")
for s in list_of_strings:
w.wrap(s)
# ...
Esta clase y su wrap El método es genial si necesitamos llamar. wrap con los mismos parámetros varias veces como se muestra arriba.
Y mientras buscamos que el TextWrapperprobemos también algunos argumentos de palabras clave más:
user = "John"
prefix = user + ": "
width = 50
wrapper = TextWrapper(initial_indent=prefix, width=width, subsequent_indent=" " * len(prefix))
messages = ["...", "...", "..."]
for m in messages:
print(wrapper.fill(m))# John: Lorem Ipsum is simply dummy text of the
# printing and typesetting industry. Lorem
# John: Ipsum has been the industry's standard dummy
# text ever since the 1500s, when an
# John: unknown printer took a galley of type and
# scrambled it to make a type specimen
Aquí podemos ver el uso de initial_indent y subsequent_indent para sangrar la primera línea del párrafo y las siguientes, respectivamente. Hay un par de opciones más, que puedes encontrar en documentos.
Además, porque TextWrapper es una clase, también podemos extenderla y anular completamente algunos de sus métodos:
from textwrap import TextWrapperclass DocumentWrapper(TextWrapper):
def wrap(self, text):
split_text = text.split('\n')
lines = [line for par in split_text for line in TextWrapper.wrap(self, par)]
return lines
text = """First line,
Another, much looooooonger line of text and/or sentence"""
d = DocumentWrapper(width=50)
print(d.fill(text))
# First line,
# Another, much looooooonger line of text and/or
# sentence
Éste es un buen ejemplo de cómo cambiar la wrap método para preservar los saltos de línea existentes e imprimirlos correctamente.
Para ver un ejemplo más completo sobre cómo manejar varios párrafos con TextWrapperverificar Este artículo.
Finalmente, textwrap También incluye dos funciones para sangría, siendo la primera dedent:
# Ugly formatting:
multiline_string = """
First line
Second line
Third line
"""from textwrap import dedent
multiline_string = """
First line
Second line
Third line
"""
print(dedent(multiline_string))
# First line
# Second line
# Third line
# Notice the leading blank line...
# You can use:
multiline_string = """\
First line
Second line
Third line
"""
# or
from inspect import cleandoc
cleandoc(multiline_string)
# 'First line\nSecond line\nThird line'
De forma predeterminada, las cadenas multilínea en Python respetan cualquier sangría utilizada en la cadena, por lo tanto, debemos usar el formato feo que se muestra en la primera variable del fragmento anterior. Pero podemos usar el dedent función para mejorar el formato: simplemente sangramos el valor de la variable como queramos y luego llamamos dedent antes de usarlo.
Alternativamente, también podríamos usar inspect.cleandoc, que también elimina la nueva línea principal. Sin embargo, esta función codifica los espacios en blanco como caracteres especiales (\n y \t), por lo que es posible que tengas que reformatearlo nuevamente.
Naturalmente, cuando hay dedententonces es necesario que haya también indent función:
from textwrap import indentindented = indent(text, " ", lambda x: not text.splitlines()[0] in x)
Simplemente proporcionamos el texto y la cadena con la que se sangrará cada línea (aquí solo 4 espacios, podríamos, por ejemplo, usar >>> para que parezca REPL). Además, podemos proporcionar un predicado que decidirá si la línea debe tener sangría o no. En el ejemplo anterior, el lambda La función hace que la primera línea de la cadena (párrafo) no tenga sangría.
textwrap es un módulo simple con solo unas pocas funciones/métodos, pero una vez más muestra que Python realmente viene con “baterias incluidas” para cosas que no necesariamente tienen que ser una biblioteca estándar, pero que pueden ahorrarle mucho tiempo cuando las necesite.
Si procesas mucho texto, también te recomiendo que consultes el toda la sección de documentos dedicado a trabajar con texto. Hay muchos más módulos y pequeñas funciones que no sabías que necesitabas. 😉
Este artículo fue publicado originalmente en martinheinz.dev