5.5 Ficheros
Aunque los ficheros encajarían más en un apartado de «entrada/salida» ya que representan un medio de almacenamiento persistente, también podrían ser vistos como estructuras de datos, puesto que nos permiten guardar la información y asignarles un cierto formato.[1]
Un fichero es un conjunto de bytes almacenados en algún dispositivo. El sistema de ficheros es la estructura lógica que alberga los ficheros y está jerarquizado a través de directorios (o carpetas). Cada fichero se identifica unívocamente a través de una ruta que nos permite acceder a él.
Python ofrece la función open() para «abrir» un fichero. Esta apertura se puede realizar en 3 modos distintos:
- Lectura del contenido de un fichero existente.
- Escritura del contenido en un fichero nuevo.
- Añadido al contenido de un fichero existente.
Veamos un ejemplo para leer el contenido de un fichero en el que se encuentran las temperaturas máximas y mínimas de cada día de la última semana. El fichero está en la subcarpeta (ruta relativa) files/temps.dat y tiene el siguiente contenido:
Lo primero será abrir el fichero:
La función open() recibe como primer argumento la ruta al fichero que queremos manejar (como un «string») y devuelve el manejador del fichero, que en este caso lo estamos asignando a una variable llamada f pero le podríamos haber puesto cualquier otro nombre.
Nota: Es importante dominar los conceptos de ruta relativa y ruta absoluta para el trabajo con ficheros. Véase este artículo de DeNovatoANovato.
Hay que tener en cuenta que la ruta al fichero que abrimos (en modo lectura) debe existir, ya que de lo contrario obtendremos un error:
Una vez abierto el fichero ya podemos proceder a leer su contenido. Para ello Python nos ofrece la posibilidad de leer todo el fichero de una vez o bien leerlo línea a línea.
Lectura completa de un fichero
Siguiendo con nuestro ejemplo de temperaturas, veamos cómo leer todo el contenido del fichero de una sola vez. Para esta operación, Python nos provee, al menos, de dos funciones:
read() Devuelve todo el contenido del fichero como una cadena de texto (str):
readlines() Devuelve todo el contenido del fichero como una lista (list) donde cada elemento es una línea:
Importante: Nótese que, en ambos casos, los saltos de línea \n siguen apareciendo en los datos leídos, por lo que habría que «limpiar» estos caracteres. Para ello se recomienda utilizar las funciones ya vistas de cadenas de texto.
Lectura línea a línea
Hay situaciones en las que interesa leer el contenido del fichero línea a línea. Imaginemos un fichero de tamaño considerable (varios GB). Si intentamos leer completamente este fichero de sola una vez podríamos ocupar demasiada RAM y reducir el rendimiento de nuestra máquina.
Es por ello que Python nos ofrece varias aproximaciones a la lectura de ficheros línea a línea. La más usada es iterar sobre el propio manejador del fichero:
Truco: Igual que pasaba anteriormente, la lectura línea por línea también incluye el salto de línea \n lo que provoca un «doble espacio» entre cada una de las salidas. Bastaría con aplicar line.split() para eliminarlo.
Para escribir texto en un fichero hay que abrir dicho fichero en modo escritura. Para ello utilizamos un argumento adicional en la función open() que indica esta operación:
Ahora ya podemos hacer uso de la función write() para enviar contenido al fichero abierto.
Supongamos que queremos volcar el contenido de una lista en dicho fichero. En este caso partimos de los códigos IATA de aeropuertos de las Islas Canarias.
Nótese:
Línea 4 Escritura de cada código en el fichero. La función write() no incluye el salto de línea por defecto, así que lo añadimos de manera explícita.
Línea 7 Cierre del fichero con la función close(). Especialmente en el caso de la escritura de ficheros, se recomienda encarecidamente cerrar los ficheros para evitar pérdida de datos.
La única diferencia entre añadir información a un fichero y escribir información en un fichero es el modo de apertura del fichero. En este caso utilizamos ’a’ por «append»:
En este caso el fichero more-data.txt se abrirá en modo añadir con lo que las llamadas a la función write() hará que aparezcan nueva información al final del contenido ya existente en dicho fichero.
Python ofrece gestores de contexto como una solución para establecer reglas de entrada y salida a un determinado bloque de código.
En el caso que nos ocupa, usaremos la sentencia with y el contexto creado se ocupará de cerrar adecuadamente el fichero que hemos abierto, liberando así sus recursos:
Línea 1 Apertura del fichero en modo lectura utilizando el gestor de contexto definido por la palabra reservada with.
Línea 2 Lectura del fichero línea a línea utilizando la iteración sobre el manejador del fichero.
Línea 3 Limpieza de saltos de línea con strip() encadenando la función split() para separar las dos temperaturas por el carácter espacio. Ver limpiar una cadena y dividir una cadena.
Línea 4 Imprimir por pantalla la temperatura mínima y la máxima.
Hay que prestar atención a la hora de escribir valores numéricos en un fichero, ya que el método write() por defecto espera ver un «string» como argumento:
Importante: Para evitar este tipo de errores, se debe convertir a str aquellos valores que queramos usar con la función write() para escribir información en un fichero de texto.
Ejercicio
Dado el fichero temperatures.txt con 12 filas (meses) y 31 columnas (temperaturas de cada día), se pide:
- Leer el fichero de datos.
- Calcular la temperatura media de cada mes.
- Escribir un fichero de salida txt con 12 filas (meses) y la temperatura media de cada mes.
Guarda el fichero en la misma carpeta en la que vas a escribir tu código. Así evitarás problemas de rutas relativas/absolutas.
AMPLIAR CONOCIMIENTOS
- Reading and Writing Files in Python
- Python Context Managers and the «with» Statement