- Introducción
- Lectura de archivos básicos en Python
- Lectura línea a línea
- Una aplicación de ejemplo
- Conclusión
Introducción
A lo largo de mi vida laboral he tenido la oportunidad de utilizar muchos conceptos y tecnologías de programación para hacer innumerables cosas. Algunas de estas cosas implican frutos de mi trabajo de relativamente poco valor, como la automatización de lo propenso a errores o lo mundano, como la generación de informes, la automatización de tareas y el reformateo general de datos. Otras han sido mucho más valiosas, como el desarrollo de productos de datos, aplicaciones web y tuberías de análisis y procesamiento de datos. Una cosa que es notable en casi todos estos proyectos es la necesidad de simplemente abrir un archivo, analizar su contenido, y hacer algo con él.
Sin embargo, ¿qué hacer cuando el archivo que está tratando de consumir es bastante grande? Qué pasa si el archivo tiene varios GB de datos o más? De nuevo, este ha sido otro aspecto frecuente en mi carrera como programador, que ha transcurrido principalmente en el sector de la biotecnología, donde es habitual encontrarse con archivos de más de 1 TB de tamaño.
La respuesta a este problema es leer en trozos un archivo a la vez, procesarlo, y luego liberarlo de la memoria para poder sacar y procesar otro trozo hasta que se haya procesado todo el archivo masivo. Aunque depende del programador determinar un tamaño de trozo adecuado, para muchas aplicaciones es conveniente procesar un archivo línea a línea.
A lo largo de este artículo cubriremos una serie de ejemplos de código para mostrar cómo leer archivos línea a línea. En caso de que quieras probar algunos de estos ejemplos por ti mismo, el código utilizado en este artículo se puede encontrar en el siguiente repositorio de GitHub.
Ejecución básica de archivos en Python
Siendo un gran lenguaje de programación de propósito general, Python tiene una serie de funcionalidades de ejecución de archivos muy útiles en su biblioteca estándar de funciones y módulos incorporados. La función incorporada open()
es la que se utiliza para abrir un objeto de archivo, ya sea para leer o escribir.
fp = open('path/to/file.txt', 'r')
La función open()
recibe múltiples argumentos. Nos centraremos en los dos primeros, siendo el primero un parámetro de cadena posicional que representa la ruta del archivo que debe abrirse. El segundo parámetro opcional es también una cadena, que especifica el modo de interacción que se pretende para el objeto archivo que devuelve la llamada a la función. Los modos más comunes se enumeran en la siguiente tabla, siendo el predeterminado ‘r’ para la lectura.
Modo | Descripción |
---|---|
r |
Abrir para leer texto sin formato |
w |
Abrir para escribir texto sin formato |
a |
|
rb |
|
wb |
Abrir para escribir datos binarios |
Una vez que se han escrito o leído todos los datos deseados para un objeto de archivo es necesario cerrar el archivo para que se puedan reasignar los recursos en el sistema operativo en el que se está ejecutando el código.
fp.close()
A menudo verás muchos fragmentos de código en Internet o en programas en la naturaleza que no cierran explícitamente los objetos de archivo que se han generado de acuerdo con el ejemplo anterior. Siempre es una buena práctica cerrar un recurso de objeto de archivo, pero muchos de nosotros somos demasiado perezosos u olvidadizos para hacerlo o pensamos que somos inteligentes porque la documentación sugiere que un objeto de archivo abierto se cerrará por sí mismo una vez que el proceso termine. Esto no es siempre el caso.
En lugar de insistir en lo importante que es llamar siempre a close()
en un objeto de archivo, me gustaría proporcionar una forma alternativa y más elegante de abrir un objeto de archivo y asegurar que el intérprete de Python limpie después de nosotros 🙂
with open('path/to/file.txt') as fp: # do stuff with fp
Simplemente usando la palabra clave with
(introducida en Python 2.5) para envolver nuestro código para abrir un objeto de archivo, los internos de Python harán algo similar al siguiente código para asegurar que no importa que el objeto de archivo se cierre después de su uso.
try: fp = open('path/to/file.txt') # do stuff with fpfinally: fp.close()
Cualquiera de estos dos métodos son adecuados, siendo el primer ejemplo la forma más «pitónica».
Lectura línea a línea
Ahora, vamos a llegar a leer realmente en un archivo. El objeto archivo devuelto por open()
tiene tres métodos explícitos comunes (read
readline
, y readlines
) para leer los datos y una forma más implícita.
El método read
leerá todos los datos en una cadena de texto. Esto es útil para los archivos más pequeños en los que te gustaría hacer la manipulación de texto en todo el archivo, o cualquier otra cosa que te convenga. Luego está readline
que es una forma útil de leer sólo cantidades incrementales de líneas individuales a la vez y devolverlas como cadenas. El último método explícito, readlines
, leerá todas las líneas de un archivo y las devolverá como una lista de cadenas.
Como se mencionó anteriormente, puedes utilizar estos métodos para cargar sólo pequeños trozos del archivo a la vez. Para hacer esto con estos métodos, puedes pasarles un parámetro que indique cuántos bytes cargar a la vez. Este es el único argumento que aceptan estos métodos.
A continuación se muestra una implementación para leer un archivo de texto una línea a la vez, que se realiza a través del método readline()
.
Nota: Para el resto de este artículo voy a demostrar cómo leer en el texto del libro La «Ilíada de Homero», que se puede encontrar en gutenberg.org, así como en el repo de GitHub donde está el código para este artículo.
En readline.py encontrarás el siguiente código. En la terminal si ejecutas $ python readline.py
podrás ver la salida de la lectura de todas las líneas de la Ilíada, así como sus números de línea.
El fragmento de código anterior abre un objeto de archivo almacenado como una variable llamada fp
, luego lee una línea cada vez llamando a readline
en ese objeto de archivo de forma iterativa en un bucle while
y lo imprime en la consola.
Ejecutando este código deberías ver algo como lo siguiente:
$ python forlinein.py Line 0: BOOK ILine 1: Line 2: The quarrel between Agamemnon and Achilles--Achilles withdrawsLine 3: from the war, and sends his mother Thetis to ask Jove to helpLine 4: the Trojans--Scene between Jove and Juno on Olympus.Line 5: Line 6: Sing, O goddess, the anger of Achilles son of Peleus, that broughtLine 7: countless ills upon the Achaeans. Many a brave soul did it sendLine 8: hurrying down to Hades, and many a hero did it yield a prey to dogs andLine 9: vultures, for so were the counsels of Jove fulfilled from the day on...
Aunque esto está perfectamente bien, hay una última forma que mencioné fugazmente antes, que es menos explícita pero un poco más elegante, que prefiero enormemente. Esta última forma de leer un archivo línea por línea incluye iterar sobre un objeto archivo en un bucle for
, asignando cada línea a una variable especial llamada line
. El fragmento de código anterior se puede replicar en el siguiente código, que se encuentra en el script de Python forlinein.py:
filepath = 'Iliad.txt'with open(filepath) as fp: for cnt, line in enumerate(fp): print("Line {}: {}".format(cnt, line))
En esta implementación estamos aprovechando una funcionalidad incorporada en Python que nos permite iterar sobre el objeto archivo de forma implícita utilizando un bucle for
en combinación con el uso del objeto iterable fp
. Esto no sólo es más sencillo de leer, sino que también requiere menos líneas de código para escribir, lo que siempre es una mejor práctica digna de seguir.
Una aplicación de ejemplo
Sería negligente escribir una aplicación sobre cómo consumir información en un archivo de texto sin demostrar al menos un uso trivial de cómo utilizar tan digna habilidad. Dicho esto, voy a demostrar una pequeña aplicación que se encuentra en wordcount.py, que calcula la frecuencia de cada palabra presente en «La Ilíada de Homero» utilizada en los ejemplos anteriores. Esto crea una simple bolsa de palabras, que se utiliza comúnmente en aplicaciones de PNL.
El código anterior representa un script de python de línea de comandos que espera una ruta de archivo pasada como argumento. El script utiliza el módulo os
para asegurarse de que la ruta de archivo pasada es un archivo que existe en el disco. Si la ruta existe entonces cada línea del archivo es leída y pasada a una función llamada record_word_cnt
como una lista de cadenas, delimitadas los espacios entre las palabras así como un diccionario llamado bag_of_words
. La función record_word_cnt
cuenta cada instancia de cada palabra y la registra en el diccionario bag_of_words
.
Una vez leídas todas las líneas del archivo y registradas en el diccionario bag_of_words
, se realiza una última llamada a la función order_bag_of_words
, que devuelve una lista de tuplas en formato (palabra, recuento de palabras), ordenadas por recuento de palabras. La lista de tuplas devuelta se utiliza para imprimir las 10 palabras más frecuentes.
Conclusión
Así pues, en este artículo hemos explorado las formas de leer un archivo de texto línea a línea de dos maneras, incluyendo una forma que me parece un poco más pitónica (siendo esta la segunda forma demostrada en forlinein.py). Para terminar, he presentado una aplicación trivial que es potencialmente útil para leer y preprocesar datos que podrían ser utilizados para el análisis de texto o el análisis de sentimiento.
0 comentarios