![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Cuando un programa se est� ejecutando, sus datos est�n en la memoria. Cuando un programa termina, o se apaga el computador, los datos de la memoria desaparecen. Para almacenar los datos de forma permanente debe usted ponerlos en un archivo. Normalmente los archivos se guardan en un disco duro, disquete o CD-ROM.
Cuando hay un gran n�mero de archivos, suelen estar organizados en directorios (tambi�n llamados "carpetas"). Cada archivo se identifica con un nombre �nico, o una combinaci�n de nombre de archivo y nombre de directorio.
Leyendo y escribiendo archivos, los programas pueden intercambiar informaci�n entre ellos y generar formatos imprimibles como PDF.
Trabajar con archivos se parece mucho a trabajar con libros. Para usar un libro, tiene que abrirlo. Cuando ha terminado, tiene que cerrarlo. Mientras el libro est� abierto, puede escribir en �l o leer de �l. En cualquier caso, sabe en qu� lugar del libro se encuentra. Casi siempre lee el libro seg�n su orden natural, pero tambi�n puede ir saltando de una p�gina a otra.
Todo esto sirve tambi�n para los archivos. Para abrir un archivo, especifique su nombre e indique si quiere leer o escribir.
La apertura de un archivo crea un objeto archivo. En este ejemplo, la variable f apunta al nuevo objeto archivo.
>>> f = open("test.dat","w")
>>> print f
<open file 'test.dat', mode 'w' at fe820>
La funci�n open toma dos argumentos. El primero es el nombre del archivo y el segundo es el modo. El modo 'w' (write) significa que lo estamos abriendo para escribir.
Si no hay un archivo llamado test.dat se crear�. Si ya hay uno, el archivo que estamos escribiendo lo reemplazar�.
Al imprimir el objeto archivo, vemos el nombre del archivo, el modo y la localizaci�n del objeto.
Para meter datos en el archivo invocamos al m�todo writesobre el objeto archivo:
>>> f.write("Ya es hora")
>>> f.write("de cerrar el archivo")
El cierre del archivo le dice al sistema que hemos terminado de escribir y deja el archivo listo para leer:
>>> f.close()
Ya podemos abrir el archivo de nuevo, esta vez para lectura, y poner su contenido en una cadena. Esta vez el argumento de modo es 'r' (read) para lectura:
>>> f = open("test.dat","r")
Si intentamos abrir un archivo que no existe, recibimos un mensaje de error:
>>> f = open("test.cat","r")
IOError: [Errno 2] No such file or directory: 'test.cat'
Como era de esperar, el m�todo read lee datos del archivo. Sin argumentos, lee el archivo completo:
>>> text = f.read()
>>> print text
Ya es horade cerrar el archivo
No hay un espacio entre "hora" y "de" porque no escribimos un espacio entre las cadenas.
read tambi�n puede aceptar un argumento que le indica cu�ntos caracteres leer:
>>> f = open("test.dat","r")
>>> print f.read(7)
Ya es h
Si no quedan suficientes caracteres en el archivo, read devuelve los que haya. Cuando llegamos al final del archivo, read devuelve una cadena vac�a:
>>> print f.read(1000006)
orade cerrar el archivo
>>> print f.read()
>>>
La siguiente funci�n copia un archivo, leyendo y escribiendo los caracteres de cincuenta en cincuenta. El primer argumento es el nombre del archivo original; el segundo es el nombre del archivo nuevo:
def copiaArchivo(archViejo, archNuevo):
f1 = open(archViejo, "r")
f2 = open(archNuevo, "w")
while 1:
texto = f1.read(50)
if texto == "":
break
f2.write(texto)
f1.close()
f2.close()
return
La sentencia break es nueva. Su ejecuci�n interrumpe el bucle; el flujo de la ejecuci�n pasa a la primera sentencia tras el bucle.
En este ejmplo, el bucle while es infinito porque el valor 1 siempre es verdadero. La �nica forma de salir del bucle es ejecutar break, lo que sucede cuando textoes una cadena vac�a, lo que sucede cuando llegamos al final del archivo.
Un archivo de texto es un archivo que contiene caracteres imprimibles y espacios organizados en l�neas separadas por caracteres de salto de l�nea. Como Python est� dise�ado espec�ficamente para procesar archivos de texto, proporciona m�todos que facilitan la tarea.
Para hacer una demostraci�n, crearemos un archivo de texto con tres l�neas de texto separadas por saltos de l�nea:
>>> f = open("test.dat","w")
>>> f.write("l�nea uno\nl�nea dos\nl�nea tres\n")
>>> f.close()
El m�todo readline lee todos los caracteres hasta e inclusive el siguiente salto de l�nea:
>>> f = open("test.dat","r")
>>> print f.readline()
l�nea uno
>>>
readlines devuelve todas las l�neas que queden como una lista de cadenas:
>>> print f.readlines()
['l�nea dos\012', 'l�nea tres\012']
En este caso, la salida est� en forma de lista, lo que significa que las cadenas aparecen con comillas y el car�cter de salto de l�nea aparece como la secuencia de escape <br>012.
Al final del archivo, readline devuelve una cadena vac�a y readlines devuelve una lista vac�a:
>>> print f.readline()
>>> print f.readlines()
[]
Lo que sigue es un ejemplo de un programa de proceso de l�neas. filtraArchivo hace una copia de archViejo, omitiendo las l�neas que comienzan por #:
def filtraArchivo(archViejo, archNuevo):
f1 = open(archViejo, "r")
f2 = open(archNuevo, "w")
while 1:
texto = f1.readline()
if texto == "":
break
if texto[0] == '#':
continue
f2.write(texto)
f1.close()
f2.close()
return
La sentencia continue termina la iteraci�n actual del bucle, pero sigue haciendo bucles. El flujo de ejecuci�n pasa al principio del bucle, comprueba la condici�n y contin�a en consecuencia.
As�, si texto es una cadena vac�a, el bucle termina. Si el primer car�cter de texto es una almohadilla, el flujo de ejecuci�n va al principio del bucle. S�lo si ambas condiciones fallan copiamos textoen el archivo nuevo.
El argumento de write debe ser una cadena, as� que si queremos poner otros valores en un archivo, tenemos que convertirlos antes en cadenas. La forma m�s f�cil de hacerlo es con la funci�n str:
>>> x = 52
>>> f.write (str(x))
Una alternativa es usar el operador de formato %. Cuando aplica a enteros, % es el operador de m�dulo. Pero cuando el primer operando es una cadena, % es el operador de formato.
El primer operando es la cadena de formato, y el segundo operando es una tupla de expresiones. El resultado es una cadena que contiene los valores de las expresiones, formateados de acuerdo a la cadena de formato.
A modo de ejemplo simple, la secuencia de formato '%d'significa que la primera expresi�n de la tupla deber�a formatearse como un entero. Aqu� la letra d quiere decir "decimal":
>>> motos = 52
>>> "%d" % motos
'52'
El resultado es la cadena '52', que no debe confundirse con el valor entero 52.
Una secuencia de formato puede aparecer en cualquier lugar de la cadena de formato, de modo que podemos incrustar un valor en una frase:
>>> motos = 52
>>> "En julio vendimos %d motos." % motos
'En julio vendimos 52 motos.'
La secuencia de formato '%f' formatea el siguiente elemento de la tupla como un n�mero en coma flotante, y '%s' formatea el siguiente elemento como una cadena:
>>> "En %d d�as ingresamos %f millones de %s."\
% (34,6.1,'d�lares')
'En 34 d�as ingresamose 6.100000 miliones de d�lares.'
Por defecto, el formato de coma flotante imprime seis decimales.
El n�mero de expresiones en la tupla tiene que coincidir con el n�mero de secuencias de formato de la cadena. Igualmente, los tipos de las expresiones deben coincidir con las secuencias de formato:
>>> "%d %d %d" % (1,2)
TypeError: not enough arguments for format string
>>> "%d" % 'd�lares'
TypeError: illegal argument type for built-in operation
En el primer ejemplo, no hay suficientes expresiones; en el segundo, la expresi�n es de un tipo incorrecto.
Para tener m�s control sobre el formato de los n�meros, podemos detallar el n�mero de d�gitos como parte de la secuencia de formato:
>>> "%6d" % 62
' 62'
>>> "%12f" % 6.1
' 6.100000'
El n�mero tras el signo de porcentaje es el n�mero m�nimo de espacios que ocupar� el n�mero. Si el valor necesita menos d�gitos, se a�aden espacios en blanco delante del n�mero. Si el n�mero de espacios es negativo, se a�aden los espacios tras el n�mero:
>>> "%-6d" % 62
'62 '
Tambi�n podemos especificar el n�mero de decimales para los n�meros en coma flotante:
>>> "%12.2f" % 6.1
' 6.10'
En este ejemplo, el resultado ocupa doce espacios e incluye dos d�gitos tras la coma. Este formato es �til para imprimir cantidades de dinero con las comas alineadas.
Imagine, por ejemplo, un diccionario que contiene los nombres de los estudiantes como clave y las tarifas horarias como valores. He aqu� una funci�n que imprime el contenido del diccionario como un informe formateado:
def informe (tarifas) :
estudiantes = tarifas.keys()
estudiantes.sort()
for estudiante in estudiantes :
print "%-20s %12.02f" % (estudiante, tarifas[estudiante])
Para probar la funci�n, crearemos un peque�o diccionario e imprimiremos el contenido:
>>> tarifas = {'mar�a': 6.23, 'jos�': 5.45, 'jes�s': 4.25}
>>> informe (tarifas)
jos� 5.45
jes�s 4.25
mar�a 6.23
Controlando la anchura de cada valor nos aseguramos de que las columnas van a quedar alineadas, siempre que los nombres tengan menos de veinti�n caracteres y las tarifas sean menos de mil millones la hora.
Cuando usted crea un archivo nuevo abri�ndolo y escribiendo, el nuevo archivo va al directorio en uso (aqu�l en el que etuviese al ejecutar el programa). Del mismo modo, cuando abre un archivo para leerlo, Python lo busca en el directorio en uso.
Si quiere abrir un archivo de cualquier otro sitio, tiene que especificar la ruta del archivo, que es el nombre del directorio (o carpeta) donde se encuentra �ste:
>>> f = open("/usr/share/dict/words","r")
>>> print f.readline()
Aarhus
Este ejemplo abre un archivo llamado words que est� en un directorio llamado dict, que est� en share, que est� en usr, que est� en el directorio de nivel superior del sistema, llamado /.
No puede usar / como parte del nombre de un archivo; est� reservado como delimitador entre nombres de archivo y directorios.
El archivo /usr/share/dict/words contiene una lista de palabras en orden alfab�tico, la primera de las cuales es el nombre de una universidad danesa.
Para poner valores en un archivo, debe convertirlos en cadenas. Ya ha visto c�mo hacerlo con str:
>>> f.write (str(12.3))
>>> f.write (str([1,2,3]))
El problema es que cuando vuelve usted a leer el valor, obtiene una cadena. Ha perdido la informaci�n del tipo de dato original. En realidad, no puede distinguir d�nde termina un valor y comienza el siguiente:
>>> f.readline()
'12.3[1, 2, 3]'
La soluci�n es el encurtido, llamado as� porque "conserva" estructuras de datos. El m�dulo pickle contiene las �rdenes necesarias. Para usarlo, importe pickle y luego abra el archivo de la forma habitual:
>>> import pickle
>>> f = open("test.pck","w")
Para almacenar una estructura de datos, use el m�todo dumpy luego cierre el archivo de la forma habitual:
>>> pickle.dump(12.3, f)
>>> pickle.dump([1,2,3], f)
>>> f.close()
Ahora podemos abrir el archivo para leer y cargar las estructuras de datos que volcamos ah�:
>>> f = open("test.pck","r")
>>> x = pickle.load(f)
>>> x
12.3
>>> type(x)
<type 'float'>
>>> y = pickle.load(f)
>>> y
[1, 2, 3]
>>> type(y)
<type 'list'>
Cada vez que invocamos load obtenemos un valor del archivo, completo con su tipo original.
Siempre que ocurre un error en tiempo de ejecuci�n, se crea una excepci�n. Normalmente el programa se para y Pythton presenta un mensaje de error.
Por ejemplo, la divisi�n por cero crea una excepci�n:
>>> print 55/0
ZeroDivisionError: integer division or modulo
Un elemento no existente en una lista hace lo mismo:
>>> a = []
>>> print a[5]
IndexError: list index out of range
O el acceso a una clave que no est� en el diccionario:
>>> b = {}
>>> print b['qu�']
KeyError: qu�
En cada caso, el mensaje de error tiene dos partes: el tipo de error antes de los dos puntos y detalles sobre el error depu�s de los dos puntos. Normalmente Python tambi�n imprime una traza de d�nde se encontraba el programa, pero la hemos omitido en los ejemplos.
A veces queremos realizar una operaci�n que podr�a provocar una excepci�n, pero no queremos que se pare el programa. Podemos manejar la excepci�n usando las sentencias try y except.
Por ejemplo, podemos preguntar al usuario por el nombre de un archivo y luego intentar abrirlo. Si el archivo no existe, no queremos que el programa se pare; queremos manejar la excepci�n.
nombreArch = raw_input('Introduce un nombre de archivo: ')
try:
f = open (nombreArch, "r")
except:
print 'No hay ning�n archivo que se llame', nombreArch
La sentencia try ejecuta las sentencias del primer bloque. Si no se produce ninguna excepci�n, pasa por alto la sentencia except. Si ocurre cualquier excepci�n, ejecuta las sentencias de la rama except y despu�s contin�a.
Podemos encapsular esta capacidad en una funci�n: existe acepta un nombre de archivo y devuelve verdadero si el archivo existe y falso si no:
def existe(nombreArch):
try:
f = open(nombreArch)
f.close()
return 1
except:
return 0
Puede usar m�ltiples bloques except para manejar diferentes tipos de excepciones. El Manual de Referencia de Python contiene los detalles.
Si su programa detecta una condici�n de error, puede hacer que lance (raise en ingl�s) una excepci�n. Aqu� tiene usted un ejemplo que acepta una entrada del usuario y comprueba si es 17. Suponiendo que 17 no es una entrada v�lida por cualquier raz�n, lanzamos una excepci�n.
def tomaNumero () : # Recuerde, los acentos est�n
x = input ('Elige un n�mero: ') # prohibidos en los nombres
if x == 17 : # de funciones y variables!
raise 'ErrorN�meroMalo', '17 es un mal n�mero'
return x
La sentencia raise acepta dos argumentos: el tipo de excepci�n e informaci�n espec�fica acerca del error. ErrorN�meroMaloes un nuevo tipo de excepci�n que hemos inventado para esta aplicaci�n.
Si la funci�n llamada tomaNumero maneja el error, el programa puede continuar; en caso contrario, Python imprime el mensaje de error y sale:
>>> tomaNumero ()
Elige un n�mero: 17
ErrorN�meroMalo: 17 es un mal n�mero
El mensaje de error incluye el tipo de excepci�n y la informaci�n adicional que usted proporcion�.
Como ejercicio, escriba una funci�n que use tomaNumeropara leer un n�mero del teclado y que maneje la excepci�n ErrorN�meroMalo.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |