| You are here: Inicio > Inmersión en Python > Excepciones y gestión de ficheros > Trabajo con objetos de fichero | << >> | ||||
Inmersión en PythonPython de novato a experto |
|||||
Python incorpora una función, open, para abrir ficheros de un disco. open devuelve un objeto de fichero, que tiene métodos y atributos para obtener información sobre el fichero abierto y manipularlo.
>>> f = open("/music/_singles/kairo.mp3", "rb")>>> f
<open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.mode
'rb' >>> f.name
'/music/_singles/kairo.mp3'
| El método open puede tomar hasta tres parámetros: un nombre de fichero, un modo y un parámetro para búfer. Sólo el primero, el nombre, es obligatorio; los otros dos son opcionales. Si no lo especifica, el fichero se abrirá en modo lectura y texto. Aquí estamos abriendo el fichero en modo binario (print open.__doc__ muestra una gran explicación de todos los modos posibles). | |
| La función open devuelve un objeto (a estas alturas, esto no debería sorprenderle). Un objeto de fichero tiene varios atributos útiles. | |
| El atributo mode de un objeto de fichero nos dice en qué modo se abrió. | |
| El atributo name de un objeto de fichero nos dice el nombre del fichero que el objeto ha abierto. |
Tras abrir un fichero, lo más importante que querrá hacer es leerlo, como se muestra en el siguiente ejemplo.
>>> f <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.tell()0 >>> f.seek(-128, 2)
>>> f.tell()
7542909 >>> tagData = f.read(128)
>>> tagData 'TAGKAIRO****THE BEST GOA ***DJ MARY-JANE*** Rave Mix 2000http://mp3.com/DJMARYJANE \037' >>> f.tell()
7543037
Los ficheros abiertos consumen recursos del sistema, y dependiendo del modo del fichero, puede que otros programas no puedan acceder a ellos. Es importante cerrar los ficheros tan pronto como haya terminado con ellos.
>>> f <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.closedFalse >>> f.close()
>>> f <closed file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.closed
True >>> f.seek(0)
Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: I/O operation on closed file >>> f.tell() Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: I/O operation on closed file >>> f.read() Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: I/O operation on closed file >>> f.close()
| El atributo closed de un objeto de fichero indica si el objeto tiene abierto un fichero o no. En este caso, el fichero sigue abierto (closed es False). | |
| Para cerrar un fichero, llame al método close del objeto. Esto libera el bloqueo (si lo hubiera) que estaba manteniendo sobre el fichero, activa la escritura de búfers (si los hubiera) que el sistema aún no haya escrito realmente, y libera los recursos del sistema. | |
| El atributo closed confirma que el fichero está cerrado. | |
| Sólo porque un fichero esté cerrado no significa que el objeto deje de existir. La variable f continuará existiendo hasta que salga de ámbito o sea eliminada manualmente. Sin embargo, ninguno de los métodos que manipula ficheros abiertos funcionará una vez cerrado el fichero; todos lanzarán una excepción. | |
| Invocar close en un objeto de fichero cuyo fichero ya está cerrado no lanza una excepción; falla sin advertirlo. |
Ahora ya ha visto bastante para comprender el código de gestión de ficheros en el ejemplo fileinfo.py del capítulo anterior. Este ejemplo le muestra cómo abrir y leer un fichero de forma segura y lidiar con los errores elegantemente.
try:
fsock = open(filename, "rb", 0)
try:
fsock.seek(-128, 2)
tagdata = fsock.read(128)
finally:
fsock.close()
.
.
.
except IOError:
pass | Como abrir y leer ficheros tiene su riesgo y puede provocar una excepción, todo el código está encapsulado en un bloque try...except. (¡Eh!, ¿no es maravilloso el sangrado estándarizado? Aquí es donde empezará a apreciarlo). | |
| La función open puede lanzar una IOError (puede que el fichero no exista). | |
| El método seek puede lanzar una IOError (puede que el fichero sea más pequeño que 128 bytes). | |
| El método read puede lanzar una IOError (puede que el disco tenga sectores defectuosos, o esté en una unidad de red y ésta acabe de caerse). | |
| Esto es nuevo: un bloque try...finally. Una vez la función open consiga abrir el fichero con éxito, querrá estar absolutamente seguro de cerrarlo, incluso si los métodos seek o read lanzan una excepción. Para esto es el bloque try...finally: el código en el bloque finally se ejecutará siempre, incluso si algo en el bloque try lanza una excepción. Piense en ello como código que se ha de ejecutar al salir, independientemente de lo que haya sucedido en medio. | |
| Por fin, gestionamos la excepción IOError. Podría ser la IOError lanzada por la llamada a open, seek o read. En este caso no nos importa, porque todo lo que vamos a hacer es ignorarlo en silencio y continuar (recuerde, pass es una sentencia de Python que no hace nada). Eso es perfectamente válido; “gestionar” una excepción puede querer decir no hacer nada, pero explícitamente. Sigue contando como gestión, y el proceso continuará de forma normal en la siguiente línea de código tras el bloque try...except. |
Como cabría esperar, también podemos escribir en ficheros de la misma manera que podemos leer de ellos. Hay dos modos básicos de escritura:
Cualquiera de los modos creará el fichero automáticamente si no existía ya, de manera que no se necesita ningún tipo de molesta lógica "si el fichero de registro no existe aún, crea un fichero nuevo vacío de manera que puedas abrirlo por primera vez".
>>> logfile = open('test.log', 'w')>>> logfile.write('prueba con éxito')
>>> logfile.close() >>> print file('test.log').read()
prueba con éxito >>> logfile = open('test.log', 'a')
>>> logfile.write('línea 2') >>> logfile.close() >>> print file('test.log').read()
prueba con éxitolínea 2
<< Excepciones y gestión de ficheros |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
Iteración con bucles for >> |