Un archivo es información identificada con un nombre que puede ser almacenada de manera permanente en el directorio de un dispositivo. Hasta ahora, hemos estado leyendo y escribiendo en la entrada y salida estándar. Ahora, veremos cómo usar los archivos de datos reales.
Python proporciona funciones y métodos básicos necesarios para manipular archivos de forma predeterminada. Puede realizar la mayor parte de la manipulación de archivos utilizando un objeto de archivo.
Antes de poder leer o escribir un archivo, debes abrirlo usando la función open () integrada de Python. Esta función crea un objeto de archivo, que se utilizará para llamar a otros métodos de soporte asociados con él.
** Sintaxis **
file object = open(file_name [, access_mode])
Aquí están los detalles del parámetro:
file_name: El argumento file_name es una cadena que contiene el nombre del archivo al que desea acceder.
access_mode: El modo de acceso determina el modo en el que se debe abrir el archivo, es decir, leer(read), escribir(write), añadir(append), etc. A continuación se muestra una lista completa de valores posibles en la tabla. Este es un parámetro opcional y se lee el modo de acceso de archivo predeterminado (r)
Aquí hay una lista de los diferentes modos de abrir un archivo:
Modos | Descripcion |
---|---|
r | Abre un archivo sólo para lectura. El puntero del archivo se coloca al principio del archivo. Este es el modo por defecto. |
rb | Abre un archivo para la lectura sólo en formato binario. El puntero del archivo se coloca al principio del archivo. Este es el modo por defecto. |
r+ | Abre un archivo para leer y escribir. El puntero de archivo colocado al principio del archivo. |
rb+ | Abre un archivo para lectura y escritura en formato binario. El puntero de archivo colocado al principio del archivo. |
w | Abre un archivo para la escritura solamente. Sobrescribe el archivo si existe el archivo. Si el archivo no existe, crea un nuevo archivo para la escritura. |
wb | Abre un archivo para escribir sólo en formato binario. Sobrescribe el archivo si existe el archivo. Si el archivo no existe, crea un nuevo archivo para la escritura. |
w+ | Abre un archivo para escribir y leer. Sobreescribe el archivo existente si existe el archivo. Si el archivo no existe, crea un nuevo archivo para leer y escribir. |
wb+ | Abre un archivo para escribir y leer en formato binario. Sobreescribe el archivo existente si existe el archivo. Si el archivo no existe, crea un nuevo archivo para leer y escribir. |
a | Abre un archivo para agregar. El puntero de archivo está al final del archivo si existe el archivo. Es decir, el archivo está en el modo de agregación. Si el archivo no existe, crea un nuevo archivo para la escritura. |
ab | Abre un archivo para anexar en formato binario. El puntero de archivo está al final del archivo si existe el archivo. Es decir, el archivo está en el modo de agregación. Si el archivo no existe, crea un nuevo archivo para la escritura. |
a+ | Abre un archivo para agregar y leer. El puntero de archivo está al final del archivo si existe el archivo. El archivo se abre en el modo de agregación. Si el archivo no existe, crea un nuevo archivo para leer y escribir. |
ab+ | Abre un archivo para agregar y leer en formato binario. El puntero de archivo está al final del archivo si existe el archivo. El archivo se abre en el modo de agregación. Si el archivo no existe, crea un nuevo archivo para leer y escribir. |
Una vez que se abre un archivo y tiene un objeto de archivo, puede obtener información relacionada con ese archivo.
Aquí hay una lista de todos los atributos relacionados con el objeto file:
Atributo | Descripción |
---|---|
file.closed | Devuelve true si el archivo está cerrado, false de lo contrario. |
file.mode | Devuelve el modo de acceso con el que se abrió el archivo. |
file.name | Devuelve el nombre del archivo. |
Ahora veamos un ejemplo:
fo = open("foo.txt", "wb")
print ("Name of the file: ", fo.name)
print ("Closed or not : ", fo.closed)
print ("Opening mode : ", fo.mode)
fo.close() # Método close() OJO METODO NO ATRIBUTO!! NO CONFUNDIR con .closed (atributo)
Name of the file: foo.txt Closed or not : False Opening mode : wb
El método close() de un objeto de archivo vacía cualquier información no escrita y cierra el objeto de archivo, después de lo cual no se puede realizar más escritura.
Python cierra automáticamente un archivo cuando el objeto de referencia de un archivo se reasigna a otro archivo. Es una buena práctica utilizar el método close () para cerrar un archivo.
El objeto file proporciona un conjunto de métodos de acceso para facilitar nuestras vidas. Veremos cómo usar los métodos read() y write() para leer y escribir archivos.
El método write() escribe cualquier cadena en un archivo abierto. Es importante tener en cuenta que las cadenas de Python pueden tener datos binarios y no sólo texto.
El método write () no agrega un carácter de nueva línea ('\ n') al final de la cadena
# Copien esto en script, luego de ejecutar se creará un archivo llamado foo1.txt, abránlo y vean la magia ;)
# Para escribir multiples lineas usen """(triples comillas)"""
# Abriendo un archivo
fo = open("foo1.txt", "w")
fo.write("""Los ordenadores son increíblemente rápidos, precisos, y estúpidos \n
Los humanos son increíblemente lentos, imprecisos, y brillantes. \n
Juntos, su potencia está más allá de lo imaginable. """)
# Cerrando el archivo abierto
fo.close()
El método anterior creará el archivo foo.txt y escribirá el contenido dado en ese archivo y finalmente cerrará ese archivo. Si usted abriría este archivo, abŕalo y vea el resultado.
El método read() lee una cadena de un archivo abierto. Es importante tener en cuenta que las cadenas de Python pueden tener datos binarios. Aparte de los datos de texto.
En el método read() el parámetro pasado es el número de bytes que se leerán del archivo abierto. Este método comienza a leer desde el principio del archivo y si falta la cuenta, entonces intenta leer tanto como sea posible, tal vez hasta el final del archivo.
# Abriendo el archivo foo1
fo = open("foo1.txt", "r+")
# Le pasamos como argumentos 20 bytes
str = fo.read(20)
print ("La cadena leida es : ", str)
print("----------------------------------")
# Cuando hagamos nuevamente foo.read() leerá los siguientes carácteres despues de haber leido lo demás
print (fo.read())
# Cerrando el archivo abierto
fo.close()
La cadena leida es : Los ordenadores son ---------------------------------- increíblemente rápidos, precisos, y estúpidos Los humanos son increíblemente lentos, imprecisos, y brillantes. Juntos, su potencia está más allá de lo imaginable.
El método tell() le indica la posición actual dentro del archivo; En otras palabras, la próxima lectura o escritura se producirá en la posición que este metodo nos indique.
El método seek(offset [, from]) cambia la posición del archivo actual. El argumento offset indica el número de bytes que se deben mover. El argumento from especifica la posición de referencia desde donde se deben mover los bytes.
Si from está puesto a 0, significa usar el comienzo del archivo como la posición de referencia y 1 significa usar la posición actual como la posición de referencia y si se establece en 2 entonces el final del archivo se tomaría como la posición de referencia .
# Abriendo un archivo
fo = open("foo1.txt", "r+")
str = fo.read(15)
print ("La cadena leida es: ", str)
# Checkea la posicion actual
position = fo.tell()
print ("Posición actual del archivo : ", position)
# Vuelva a colocar el puntero al principio una vez más
position = fo.seek(0, 0)
str = fo.read(15)
print ("Una vez más, la cadena de lectura es: ", str)
# Cerrando el achivo abierto
fo.close()
La cadena leida es: Los ordenadores Posición actual del archivo : 15 Una vez más, la cadena de lectura es: Los ordenadores
# Este programa es una agenda telefónica
# Imprime los nombres y sus respectivos números
def print_numbers(numbers):
print("Numeros de Telefono:")
for k, v in numbers.items():
print("nombre:", k, "\t Numero:", v)
print()
# Añande un numero
def add_number(numbers, name, number):
numbers[name] = number
# Verifica si un numero se encuentra o no en la agenda
def lookup_number(numbers, name):
if name in numbers:
return "El numero es " + numbers[name]
else:
return name + " no ha sido encontrado"
# Elimina un número
def remove_number(numbers, name):
if name in numbers:
del numbers[name]
else:
print(name," no ha sido encontrado")
# Carga números
def load_numbers(numbers, filename):
in_file = open(filename, "rt")
while True:
in_line = in_file.readline()
if not in_line:
break
in_line = in_line[:-1]
name, number = in_line.split(",")
numbers[name] = number
in_file.close()
# Guarda numeros
def save_numbers(numbers, filename):
out_file = open(filename, "wt")
for k, v in numbers.items():
out_file.write(k + "," + v + "\n")
out_file.close()
# Menu de inicio
def print_menu():
print('1. Imprimir los nueros de teléfono')
print('2. Añade un numero de teléfono')
print('3. Elimina un numero de teléfono')
print('4. Busca un numero de teléfono')
print('5. Carga numeros')
print('6. Guarda numeros')
print('7. Salir')
print()
# Crea un diccionario vacio
phone_list = {}
# Inicializa la decicion como 0
menu_choice = 0
# Inicia el programa
print_menu()
while True:
menu_choice = int(input("Ingrese un numero del (1-7): "))
if menu_choice == 1:
print_numbers(phone_list)
elif menu_choice == 2:
print("Ingrese un nombre y un numero")
name = input("Nombre: ")
phone = input("Numero: ")
add_number(phone_list, name, phone)
elif menu_choice == 3:
print("Remover el nombre y numero")
name = input("Ingrese el nombre que desee eliminar: ")
remove_number(phone_list, name)
elif menu_choice == 4:
print("Busque un numero")
name = input("Nombre: ")
print(lookup_number(phone_list, name))
elif menu_choice == 5:
filename = input("Archivo a cargar: ")
load_numbers(phone_list, filename)
elif menu_choice == 6:
filename = input("Archivo a guardar: ")
save_numbers(phone_list, filename)
elif menu_choice == 7:
break
else:
print_menu()
print("Adios :c ")
1. Imprimir los nueros de teléfono 2. Añade un numero de teléfono 3. Elimina un numero de teléfono 4. Busca un numero de teléfono 5. Carga numeros 6. Guarda numeros 7. Salir Ingrese un numero del (1-7): 1 Numeros de Telefono: Ingrese un numero del (1-7): 5 Archivo a cargar: numeros.txt Ingrese un numero del (1-7): 1 Numeros de Telefono: nombre: Carla Numero: 912312121 nombre: Maria Numero: 989123876 Ingrese un numero del (1-7): 2 Ingrese un nombre y un numero Nombre: Megumi Numero: 908321786 Ingrese un numero del (1-7): 1 Numeros de Telefono: nombre: Carla Numero: 912312121 nombre: Maria Numero: 989123876 nombre: Megumi Numero: 908321786 Ingrese un numero del (1-7): 2 Ingrese un nombre y un numero Nombre: Kosaki Numero: 908123867 Ingrese un numero del (1-7): 3 Remover el nombre y numero Ingrese el nombre que desee eliminar: Carla Ingrese un numero del (1-7): 1 Numeros de Telefono: nombre: Maria Numero: 989123876 nombre: Megumi Numero: 908321786 nombre: Kosaki Numero: 908123867 Ingrese un numero del (1-7): 4 Busque un numero Nombre: Kosaki El numero es 908123867 Ingrese un numero del (1-7): 6 Archivo a guardar: numeros2.txt Ingrese un numero del (1-7): 7 Adios :c
Ahora abran el archivo numeros2.txt y vean la magia :O
En un programa podemos encontrarnos con distintos tipos de errores pero a grandes rasgos podemos decir que todos los errores pertenecen a una de las siguientes categorías.
Errores de sintaxis: estos errores son seguramente los más simples de resolver, pues son detectados por el intérprete (o por el compilador, según el tipo de lenguaje que estemos utilizando) al procesar el código fuente y generalmente son consecuencia de equivocaciones al escribir el programa. En el caso de Python estos errores son indicados con un mensaje SyntaxError. Por ejemplo, si trabajando con Python intentamos definir una función y en lugar de def escribimos dev.
Errores semánticos: se dan cuando un programa, a pesar de no generar mensajes de error, no produce el resultado esperado. Esto puede deberse, por ejemplo, a un algoritmo incorrecto o a la omisión de una sentencia.
Errores de ejecución: estos errores aparecen durante la ejecución del programa y su origen puede ser diverso. En ocasiones pueden producirse por un uso incorrecto del programa por parte del usuario, por ejemplo si el usuario ingresa una cadena cuando se espera un número. En otras ocasiones pueden deberse a errores de programación, por ejemplo si una función intenta acceder a la quinta posición de una lista de 3 elementos o realizar una división por cero. Una causa común de errores de ejecución que generalmente excede al programador y al usuario, son los recursos externos al programa, por ejemplo si el programa intenta leer un archivo y el mismo se encuentra dañado.
Tanto a los errores de sintaxis como a los semánticos se los puede detectar y corregir durante la construcción del programa ayudados por el intérprete y la ejecución de pruebas. Pero no ocurre esto con los errores de ejecución ya que no siempre es posible saber cuando ocurrirán y puede resultar muy complejo (o incluso casi imposible) reproducirlos. Es por ello que el resto de la unidad nos centraremos en cómo preparar nuestros programas para lidiar con este tipo de errores.
Los errores de ejecución son llamados comúnmente excepciones y por eso de ahora en más utilizaremos ese nombre. Durante la ejecución de un programa, si dentro de una función surge una excepción y la función no la maneja, la excepción se propaga hacia la función que la invocó, si esta otra tampoco la maneja, la excepción continua propagándose hasta llegar a la función inicial del programa y si esta tampoco la maneja se interrumpe la ejecución del programa. Veamos entonces como manejar excepciones.
Para el manejo de excepciones los lenguajes proveen ciertas palabras reservadas, que nos permiten manejar las excepciones que puedan surgir y tomar acciones de recuperación para evitar la interrupción del programa o, al menos, para realizar algunas acciones adicionales antes de interrumpir el programa.
En el caso de Python, el manejo de excepciones se hace mediante los bloques que utilizan las sentencias try, except y finally.
Dentro del bloque try se ubica todo el código que pueda llegar a levantar una excepción, se utiliza el término levantar para referirse a la acción de generar una excepción.
A continuación se ubica el bloque except, que se encarga de capturar la excepción y nos da la oportunidad de procesarla mostrando por ejemplo un mensaje adecuado al usuario. Veamos qué sucede si se quiere realizar una división por cero:
dividendo = 8
divisor = 0
cociente = dividendo / divisor
--------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-6-e22959b81d50> in <module>() 1 dividendo = 8 2 divisor = 0 ----> 3 cociente = dividendo / divisor ZeroDivisionError: division by zero
En este caso, se levantó la excepción ZeroDivisionError cuando se quiso hacer la división. Para evitar que se levante la excepción y se detenga la ejecución del programa, se utiliza el bloque try-except.
try:
cociente = dividendo / divisor
except:
print("No se pudo efectuar la division")
No se pudo efectuar la division
Tambíen podemos capturar multiples excepciones mediante la estrcutura:
try:
# aquí ponemos el código que puede lanzar excepciones
except IOError:
# entrará aquí en caso que se haya producido una excepción IOError
except ZeroDivisionError:
# entrará aquí en caso que se haya producido una excepción ZeroDivisionError
except:
# entrará aquí en caso que se haya producido una excepción que no corresponda a ninguno
# de los tipos especificados en los except previos
while True:
try:
num_str = input('Ingrese un número: ')
num = int(num_str)
print("{} / {} = {}".format(12,num, 12/num ))
break
except ValueError:
print('Ingresa un número válido')
except ZeroDivisionError:
print('Pero que el número no sea cero!')
Ingrese un número: 0 Pero que el número no sea cero! Ingrese un número: 5 12 / 5 = 2.4
Finalmente, puede ubicarse un bloque finally donde se escriben las sentencias de finalización, que son típicamente acciones de limpieza. La particularidad del bloque finally es que se ejecuta siempre, haya surgido una excepción o no. Si hay un bloque except, no es necesario que esté presente el finally, y es posible tener un bloque try sólo con finally, sin except.
import sys
try:
f = open('miarchivo.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("Error OS: {0}".format(err))
except ValueError:
print("No pude convertir el dato a un entero.")
except:
print("Error inesperado:", sys.exc_info()[0])
finally:
print("Ha terminado el bloque")
No pude convertir el dato a un entero. Ha terminado el bloque
La declaración raise permite al programador forzar a que ocurra una excepción específica. Por ejemplo:
raise NameError('How you doing?')
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-11-f5dee82ee479> in <module>() ----> 1 raise NameError('How you doing?') NameError: How you doing?
El único argumento a raise indica la excepción a generarse. Tiene que ser o una instancia de excepción, o una clase de excepción (una clase que hereda de Exception).
Si necesitás determinar cuando una excepción fue lanzada pero no querés manejarla, una forma simplificada de la instrucción raise te permite relanzarla:
try:
raise NameError('I am fine')
except NameError:
print('Acaba de ocurrir una excepción!')
raise
Acaba de ocurrir una excepción!
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-12-d3cfc816c189> in <module>() 1 try: ----> 2 raise NameError('I am fine') 3 except NameError: 4 print('Acaba de ocurrir una excepción!') 5 raise NameError: I am fine
De más está decir, que las excepciones pueden ser personalizadas según sea necesario:
class MiError(Exception):
def __init__(self, mssg, ref=''):
self.mssg = mssg
self.ref = ref
def __str__(self,):
return "Error creado: {} {}".format(self.mssg, self.ref)
try:
raise MiError("Archivos inválidos", ('a.conf','b.conf') )
except MiError as e:
print(e)
Error creado: Archivos inválidos ('a.conf', 'b.conf')
# Esta celda da el estilo al notebook
from IPython.core.display import HTML
css_file = '../styles/StyleCursoPython.css'
HTML(open(css_file, "r").read())