El módulo estándar textwrap



Versión: 2.x, 3.x.

Durante los últimos días tuve un rápido encuentro con el módulo estándar textwrap, el cual no podía ser de otra manera pues es bastante pequeño. Ésta es en parte la modalidad de Recursos Python: de las herramientas que empleo en proyectos personales y considero útiles y que puedan servir a la comunidad del lenguaje intento proveer una explicación lo más ilustrada posible.

Para prototipos rápidos, textwrap dispone la función wrap, cuyo objetivo es dividir en porciones textos extensos (probablemente para mayor legibilidad). «Extenso» es lo que el programador considere como tal cosa, en términos de cantidad de caracteres.

>>> import textwrap
>>> textwrap.wrap("Esto es un texto muy largo.", 10)
['Esto es un', 'texto muy', 'largo.']

La función retorna una lista con el texto dividido de acuerdo a la cantidad de caracteres especificados en el segundo argumento. Nótese que la división del texto siempre intenta aplicarse en los espacios en blanco, a menos que no sea posible.

>>> textwrap.wrap("EsteEsUnTextoSinEspacios", 10)
['EsteEsUnTe', 'xtoSinEspa', 'cios']

En la mayoría de los casos simplemente queremos añadir saltos de línea en lugar de realizar la división, probablemente para colocar el texto en un espacio con un ancho reducido. En esta situación bien podríamos hacer:

>>> "\n".join(textwrap.wrap("Esto es un texto muy largo.", 10))
'Esto es un\ntexto muy\nlargo.'

Y se vería de la siguiente forma al ser impreso en pantalla.

>>> print(_)
Esto es un
texto muy
largo.

Esta es exactamente la funcionalidad que provee textwrap.fill().

>>> textwrap.fill("Esto es un texto muy largo.", 10)
'Esto es un\ntexto muy\nlargo.'

Por otra parte, la función textwrap.dedent (contrario a indent, indentar) remueve espacios o tabulaciones al comienzo de cada línea del texto especificado.

# La barra invertida evita un salto de línea al comienzo.
>>> text = """\
...     A
...     B
...     C"""
>>> print(text)
        A
        B
        C
>>> print(textwrap.dedent(text))
A
B
C

Nótese que la indentación debe ser común a cada una de las líneas.

>>> text = """\
...     A
...             B
...                     C
...                             D"""
# Imprime el mismo resultado.
>>> print textwrap.dedent(text)
A
        B
                C
                        D

A partir de la versión 3.3 textwrap añade la capacidad de indentar vía indent().

>>> text = """\
... A
... B
... C"""
>>> print(textwrap.indent(text, "    "))
    A
    B
    C

El segundo argumento indica la cadena que será utilizada como indentación (4 espacios en este caso).

Un tercer argumento opcional (predicate) puede ser una función lambda que será invocada para cada línea del texto e indicará si debe aplicarse la indentación (retornando True o False). Por ejemplo, el siguiente código aplica indentación solo a las líneas que no comiencen con 4 espacios.

>>> text = """\
... A
...     B
... C
...     D"""
>>> print(textwrap.indent(text, "    ", lambda s: not s.startswith("    ")))
    A
    B
    C
    D

Python 3.4 añade textwrap.shorten. Como lo indica el nombre, permite acortar un texto en base a la cantidad de caracteres indicados (vía el parámetro width).

text = "Esto es una descripción muy larga."
>>> textwrap.shorten(text, width=30)
'Esto es una descripción [...]'
>>> textwrap.shorten(text, width=30, placeholder="...")
'Esto es una descripción muy...'

En el caso de las funciones wrap y fill, el trabajo es realizado por la clase TextWrapper, de la cual crean una instancia internamente y llaman a los métodos correspondientes. Para aplicar alguna de estas funciones a múltiples textos, consideren realizarlo de la siguiente manera para obtener mejor rendimiento.

# Crear una instancia manualmente.
wrapper = textwrap.TextWrapper(width=10)

# Ejecutar fill() en varios textos.
for text in lista_de_textos:
    print(wrapper.fill(text))

El siguiente método es mucho menos eficiente ya que crea una instancia de TextWrapper por cada llamada a fill().

# No recomendado.
for text in lista_de_textos:
    print(textwrapper.fill(text, width=10))

Para conocer todos los atributos de la clase TextWrapper o bien argumentos que pueden ser utilizados en las funciones wrap y text véase la documentación oficial del módulo.



Deja una respuesta