Python: Aprendiendo a leer

Objetivo: aproximación al trabajo con ficheros en Python, mostrando cómo leer el contenido de un archivo de texto.

Como programador, necesitas familiarizarte cuanto antes con el trabajo con ficheros. Con frecuencia tu aplicación deberá recuperar información de un fichero para su procesamiento, o bien almacenará en él el resultado de ese proceso. Es común también el intercambio de información con el exterior en ambos sentidos: la aplicación se nutre de datos externos almacenados en ficheros y genera información que se guarda nuevamente ellos después.

Nos aproximaremos al trabajo con ficheros en Python de un modo gradual y aprenderemos a realizar las tareas más típicas partiendo de lo más simple: la lectura de un archivo de texto.

Supongo que ya conoces la diferencia entre los ficheros de texto y los binarios. Expresada de un modo simple, los primeros pueden ser leídos empleando un editor de texto plano, como gedit en Linux o el bloc de notas de Windows. Más técnicamente, podríamos decir que los ficheros de texto mantienen una codificación estándar que permite la asociación de cada byte (o un grupo de ellos) con un determinado carácter de texto, mientras que en los binarios el significado de cada byte es determinado por la propia aplicación, pudiendo representar cualquier tipo de entidad.

Ya sabes que para Python todo son objetos y, naturalmente, los ficheros también. Para que podamos interactuar con un fichero, Python crea una abstracción, un objeto, a través del cual se nos ofrece una serie de métodos para que podamos trabajar con él. Hay métodos para leer, escribir o modificar el cursor (la posición en la que se realizará la lectura o escritura), por indicar algunos.

Lo primero que debemos aprender es a crear esa abstracción, el objeto sobre el cual trabajaremos para interacturar con el fichero físico real. Es lo que se conoce como abrir el fichero.

Para hacerlo disponemos de la función open(), que usaremos del siguiente modo:

nombre_del_objeto = open(fichero_real, modo_de_apertura)

nombre_del_objeto es el nombre con el que designaremos la abstracción que envolverá al fichero_real. Dependiendo del valor que indiquemos en modo_de_apertura Python construirá un tipo de objeto u otro y determinará qué tipo de operaciones podemos realizar con él.

Iremos conociendo los distintos modos en los sucesivos artículos, pero por el momento quédate con la idea de que, cuando no se especifica un modo, Python sobreentiende que se trata de un fichero tipo texto y que sólo vas a realizar operaciones de lectura. Esto es justo lo que pretendemos lograr hoy, ser capaces de leer el contenido de un archivo de texto.

Créate un fichero de pruebas y abre un intérprete de comandos en el mismo directorio.

En este ejemplo, he creado el fichero pruebas.txt, con el siguiente contenido:

Comienza el fichero con una mención a la casa de la pradera.
La segunda línea suele hallarse después de la primera.

Esta es la cuarta línea, en la tercera había una línea en blanco.
Es una verdadera lástima que esta sea la última línea.

Observa que se trata de un fichero de cinco líneas en el que he dejado la tercera expresamente en blanco.

Para leer el fichero, la primera acción a realizar es, como hemos visto, abrirlo:

>>> fichero = open('pruebas.txt')

He elegido como nombre del objeto, fichero, sin complicarme la vida más. Entre comillas, como argumento de la función open() figura el nombre del archivo. Si no se encontrase en el mismo directorio en el que hemos ejecutado Python, deberíamos especificar su path completo.

Recuerda lo dicho anteriormente: si no indicamos un segundo parámetro con el modo de apertura, se sobreentiende el siguiente: texto y lectura.

Si tienes curiosidad por saber qué tipo de objeto ha creado Python, pregúntaselo:

>>> type(fichero)
<class '_io.TextIOWrapper'>

Que es algo así como un “envoltorio de entrada y salida texto”.

Existen diversas formas de leer el fichero. Una de ellas es aprovecharnos de una particularidad muy interesante: podemos iterar sobre un fichero de texto recorriéndolo línea a línea, de modo semejante al que iteramos recorriendo una lista de principio a fin con el bucle for.

Ensayemos lo siguiente:

>>> for linea in fichero:
  print(linea)

  
Comienza el fichero con una mención a la casa de la pradera.

La segunda línea suele hallarse después de la primera.

Esta es la cuarta línea, en la tercera había una línea en blanco.

Es una verdadera lástima que esta sea la última línea.

Salvo por el detalle de que ha intercalado una línea en blanco adicional entre cada línea, el resultado es bastante decente.

Enseguida veremos cómo solucionar esto, pero antes necesito que observes un comportamiento curioso.

Vamos a intentar iterar una segunda vez y veamos qué ocurre:

>>> for linea in fichero:
  print(linea)

  
>>> 

No ha devuelto absolutamente nada. La iteración está agotada.

Python, paralelamente al proceso de lectura, actualiza un cursor indicando cúal es el siguiente elemento a leer. Como ya ha llegado al final, un nuevo intento de lectura fracasa, pues no hay nada más que leer.

¿Significa esto que no podemos leer un fichero varias veces? En absoluto. Existe un método que nos permite mover el cursor de lectura al punto deseado.

>>> fichero.seek(0)
0

Esta instrucción nos posiciona nuevamente al comienzo del fichero (carácter en la posición 0). La trataremos con detalle en otro momento, pero por ahora es suficiente con que retengas este uso.

Ya estamos en condiciones de realizar una segunda lectura, pero esta vez lo haremos sin que se impriman las líneas en blanco adicionales.

¿A qué se debe que haya dos líneas en blanco?

Python distingue una línea de otra terminándola con el carácter de nueva línea (\n). Pero, además, la función print() agrega siempre, por defecto, otro carácter de fin de línea al final, de modo que cada impresión queda separada de la anterior en una línea diferente. Por eso encontramos los dos saltos de línea: el que trae cada línea propiamente dicha más el que agrega la función print().

Para esta segunda lectura vamos a modificar la función print(), agregando un parámetro con el carácter o caracteres que deseamos que agregue al final de cada impresión, en lugar de la opción por defecto, el salto de línea. Para indicar que no queremos que agregue nada, el uso de print() debe ser el siguiente:

print(linea, end='')

De modo que nuestra iteración por líneas ahora produciría el resultado deseado:

>>> for linea in fichero:
  print(linea, end='')

  
Comienza el fichero con una mención a la casa de la pradera.
La segunda línea suele hallarse después de la primera.

Esta es la cuarta línea, en la tercera había una línea en blanco.
Es una verdadera lástima que esta sea la última línea.

Voy a presentarte a continuación un método interesante que te permite leer el fichero de una sola vez: read().

Posiciónate de nuevo al comienzo del fichero, que habrá quedado exhausto tras la lectura anterior.

>>> fichero.seek(0)
0

Y ejecuta esta nueva instrucción:

>>> fichero.read()
'Comienza el fichero con una mención a la casa de la pradera.\nLa segunda línea suele hallarse después de la primera.\n\nEsta es la cuarta línea, en la tercera había una línea en blanco.\nEs una verdadera lástima que esta sea la última línea.\n'

Devuelve un string muy largo con el contenido del fichero (probablemente tendrás que usar la barra de desplazamiento al ver esto en el navegador, pues el contenido se muestra en una única línea).

Lo importante es que se aprecia bien la estructura del fichero, con los \n separando cada línea. Fíjate también en la línea en blanco, en la posición donde está el \n\n.

Naturalmente, esta salida la obtienes a través del intérprete interactivo. Si quieres ver el resultado en un programa tendrás que usar la función print() para mostrarla.

>>> fichero.seek(0)
0
>>> print(fichero.read())
Comienza el fichero con una mención a la casa de la pradera.
La segunda línea suele hallarse después de la primera.

Esta es la cuarta línea, en la tercera había una línea en blanco.
Es una verdadera lástima que esta sea la última línea.

Una lectura con read(), al igual que la iteración, deja exhausto el fichero, posicionando el cursor de lectura al final de todo:

>>> fichero.read()
''

Presta mucha atención a esto: la cadena vacía ” es el indicativo que tiene Python para detectar que ha llegado al final del archivo, hecho que podremos utilizar en nuestro código a la hora de hacer lecturas.

Otro método que debes conocer es readline() que, a diferencia del anterior, que realiza una lectura completa, recupera cada línea de una en una:

>>> fichero.seek(0)
0
>>> fichero.readline()
'Comienza el fichero con una mención a la casa de la pradera.\n'

Como el cursor estará posicionado al comienzo de la línea siguiente, cada nueva ejecución de readline() nos recuperará la línea adecuada:

>>> fichero.readline()
'La segunda línea suele hallarse después de la primera.\n'
>>> fichero.readline()
'\n'
>>> fichero.readline()
'Esta es la cuarta línea, en la tercera había una línea en blanco.\n'
>>> fichero.readline()
'Es una verdadera lástima que esta sea la última línea.\n'
>>> fichero.readline()
''

Observa nuevamente la cadena vacía para indicar que ya hemos alcanzado el final del archivo.

A continuación, uno de mis metodos favoritos: readlines(), como el anterior, pero esta vez en plural.

Este método devuelve una lista en la que cada elemento es una línea del fichero:

>>> fichero.seek(0)
0
>>> fichero.readlines()
['Comienza el fichero con una mención a la casa de la pradera.\n', 
'La segunda línea suele hallarse después de la primera.\n', 
'\n', 
'Esta es la cuarta línea, en la tercera había una línea en blanco.\n', 
'Es una verdadera lástima que esta sea la última línea.\n']

Asocia su salida a una variable y en una única lectura tendrás una lista que podrás manipular tranquilamente a tus anchas sin preocuparte de cursores.

Para finalizar, una vez hemos terminado de usar el objeto fichero, debemos proceder a cerrarlo, liberando así la memoria que estaba consumiendo y rompiendo el vínculo con el fichero real.

>>> fichero.close()

A partir de ahí, nuestra abstracción fichero dejará de estar disponible. Si necesitaras volver a hacer uso del archivo deberías abrirlo nuevamente.

Suficiente por hoy. No olvides las tres erres: read, readline y readlines.

Javier Montero Gabarró


Python: Aprendiendo a leer


El texto de este artículo se encuentra sometido a una licencia Creative Commons del tipo CC-BY-NC-ND (reconocimiento, no comercial, sin obra derivada, 3.0 unported)


El Club del Autodidacta


Consulta el índice completo de artículos relacionados con Python.

3 opiniones en “Python: Aprendiendo a leer”

Deja un comentario