• No results found

4.4 Conclusions

5.1.1 Macroscopic average technique

11.10.

Apéndice

A continuación, el código para un programa de agenda que utiliza archivos csv. Luego, los cambios necesarios para que la agenda que utilice archivos en formato pickle, en lugar de csv.

agenda-csv.pyAgenda con los datos en csv 1 #!/usr/bin/env python 2 # encoding: latin1 3 4 import csv 5 6 ARCHIVO="agenda.csv" 7 CAMPOS=["Nombre","Apellido","Telefono","Cumpleaños"] 8 9 def leer_csv(datos_csv):

10 """ Devuelve la siguiente línea o None si se terminó el archivo. """ 11 try: 12 return datos_csv.next() 13 except: 14 return None 15 16 def leer_datos(archivo):

17 """ Carga todos los datos del archivo en una lista y la devuelve. """ 18 abierto = open(archivo) 19 datos_csv = csv.reader(abierto) 20 campos = leer_csv(datos_csv) 21 datos = [] 22 elemento = leer_csv(datos_csv) 23 while elemento: 24 datos.append(elemento) 25 elemento = leer_csv(datos_csv) 26 abierto.close() 27 return datos 28

29 def guardar_datos(datos, archivo):

30 """ Guarda los datos recibidos en el archivo. """ 31 abierto = open(archivo,"w") 32 datos_csv = csv.writer(abierto) 33 datos_csv.writerow(CAMPOS) 34 datos_csv.writerows(datos) 35 abierto.close() 36 37 def leer_busqueda():

38 """ Solicita al usuario nombre y apellido y los devuelve. """ 39 nombre = raw_input("Nombre: ")

40 apellido = raw_input("Apellido: ") 41 return (nombre,apellido)

42

43 def buscar(nombre, apellido, datos):

44 """ Busca el primer elemento que coincida con nombre y con apellido. """ 45 for elemento in datos:

46 if nombre in elemento[0] and apellido in elemento[1]: 47 return elemento

122 Unidad 11. Manejo de archivos

49

50 def menu_alta(nombre, apellido, datos):

51 """ Pregunta si se desea ingresar un nombre y apellido y 52 de ser así, pide los datos al usuario. """

53 print "No se encuentra %s %s en la agenda." % (nombre, apellido) 54 confirmacion = raw_input("¿Desea ingresarlo? (s/n) ")

55 if confirmacion.lower() != "s": 56 return 57 telefono = raw_input("Telefono: ") 58 cumple = raw_input("Cumpleaños: ") 59 datos.append([nombre,apellido,telefono,cumple]) 60 61 def mostrar_elemento(elemento):

62 """ Muestra por pantalla un elemento en particular. """ 63 print

64 print " %s %s" % (elemento[0],elemento[1]) 65 print "Telefono: %s" % elemento[2]

66 print "Cumpleaños: %s" % elemento[3] 67 print

68

69 def menu_elemento():

70 """ Muestra por pantalla las opciones disponibles para un elemento 71 existente. """

72 o = raw_input("b: borrar, m: modificar, ENTER para continuar (b/m): ") 73 return o.lower()

74

75 def modificar(viejo, nuevo, datos):

76 """ Reemplaza el elemento viejo con el nuevo, en la lista datos. """ 77 indice = datos.index(viejo)

78 datos[indice] = nuevo 79

80 def menu_modificacion(elemento, datos):

81 """ Solicita al usuario los datos para modificar una entrada. """ 82 nombre = raw_input("Nuevo nombre: ")

83 apellido = raw_input("Nuevo apellido: ") 84 telefono = raw_input("Nuevo teléfono: ") 85 cumple = raw_input("Nuevo cumpleaños: ")

86 modificar(elemento, [nombre, apellido, telefono, cumple], datos) 87

88 def baja(elemento, datos):

89 """ Elimina un elemento de la lista. """ 90 datos.remove(elemento)

91

92 def confirmar_salida():

93 """ Solicita confirmación para salir """

94 confirmacion = raw_input("¿Desea salir? (s/n) ") 95 return confirmacion.lower() == "s"

96

97 def agenda():

98 """ Función principal de la agenda.

99 Carga los datos del archivo, permite hacer búsquedas, modificar 100 borrar, y al salir guarda. """

101 datos = leer_datos(ARCHIVO) 102 fin = False

11.10. Apéndice 123

103 while not fin:

104 (nombre, apellido) = leer_busqueda() 105 if nombre == "" and apellido == "":

106 fin = confirmar_salida()

107 continue

108 elemento = buscar(nombre, apellido, datos) 109 if not elemento:

110 menu_alta(nombre, apellido, datos)

111 continue 112 mostrar_elemento(elemento) 113 opcion = menu_elemento() 114 if opcion == "m": 115 menu_modificacion(elemento, datos) 116 elif opcion == "b": 117 baja(elemento, datos) 118 guardar_datos(datos, ARCHIVO) 119 120 agenda()

agenda-pickle.pyDiferencia de agenda con datos en pickle 1 import pickle

2

3 ARCHIVO="agenda.dat" 4

5 def leer_datos(archivo):

6 """ Carga todos los datos del archivo en una lista y la devuelve. """ 7 abierto = open(archivo)

8 datos = pickle.load(archivo) 9 abierto.close()

10 return datos 11

12 def guardar_datos(datos, archivo):

13 """ Guarda los datos recibidos en el archivo. """ 14 abierto = open(archivo,"w")

15 pickle.dump(archivo, datos) 16 abierto.close()

Unidad 12

Manejo de errores y excepciones

12.1.

Errores

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 equivoca- ciones 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 fun- ció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 inco- rrecto 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.

12.2.

Excepciones

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

12.2. Excepciones 125

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.

12.2.1. Manejo de 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 = 5

>>> divisor = 0

>>> dividendo / divisor

Traceback (most recent call last): File "<stdin>", line 1, in <module>

ZeroDivisionError: integer division or modulo by zero

En este caso, se levantó la excepción ZeroDivisionError cuando se quiso hacer la divi- sió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 permite la división por cero" ...

No se permite la división por cero

Dado que dentro de un mismo bloque try pueden producirse excepciones de distinto tipo, es posible utilizar varios bloques except, cada uno para capturar un tipo distinto de excep- ción.

Esto se hace especificando a continuación de la sentencia except el nombre de la excepción que se pretende capturar. Un mismo bloque except puede atrapar varios tipos de excepciones, lo cual se hace especificando los nombres de la excepciones separados por comas a continua- ción de la palabra except. Es importante destacar que si bien luego de un bloque try puede haber varios bloques except, se ejecutará, a lo sumo, uno de ellos.

try:

# aquí ponemos el código que puede lanzar excepciones

except IOError:

# entrará aquí en caso que se haya producido # una excepción IOError