python - para - tutorial django
¿Cómo "con" es mejor que try/catch para abrir un archivo en Python? (3)
Obtuve que la declaración with
ayuda te ayuda a convertir esto:
try:
f = open(my_file)
do_stuff_that_fails()
except:
pass
finally:
f.close()
Dentro:
with open(my_file) as f:
do_stuff_that_fails()
¿Pero cómo es eso mejor? Todavía tienes que manejar el caso con el archivo que no se puede abrir (como pedirle al usuario que le diga que no tiene permisos), así que en realidad tendrías:
try:
with open(my_file) as f:
do_stuff_that_fails()
except (IOError, OSError, Failure) as e:
do_stuff_when_it_doesnt_work()
Lo cual es equivalente a:
try:
f = open(my_file)
do_stuff_that_fails()
except (IOError, OSError, Faillure) as e:
do_stuff_when_it_doesnt_work()
finally:
f.close()
Sí, ganó dos líneas, pero agregó un nivel de anidación que no facilita la lectura. ¿El propósito de la declaración with
para guardar dos líneas o me falta algo?
Parece mucho agregar una palabra clave solo para eso, así que siento que hay alguna sintaxis para manejar la prueba adicional, excepto que no sé.
En el ejemplo que das, no es mejor. Lo mejor es detectar las excepciones tan cerca del punto donde se lanzan para evitar la captura de excepciones no relacionadas del mismo tipo.
try:
file = open(...)
except OpenErrors...:
# handle open exceptions
else:
try:
# do stuff with file
finally:
file.close()
Como lamentablemente es muy detallado, la declaración with
no permite capturar excepciones lanzadas durante su evaluación. Hubo una suggestion para agregar manejo de excepciones a este efecto en la lista de correo:
with open(...) as file:
# do stuff with file
except OpenErrors...:
# handle open exceptions
Pero esto fue derribado .
Finalmente, vale la pena señalar que puede ingresar y salir directamente de los administradores de contexto de la siguiente manera:
file = open(...).__enter__()
file.__exit__(typ, val, tb)
Esto se describe con más detalle aquí y here .
Como una guía general, with
declaraciones sobresalientes para los casos donde no se esperan excepciones, y el comportamiento predeterminado "entrar / abrir / adquirir" es adecuado. Los ejemplos incluyen archivos necesarios y bloqueo simple.
Es para la gestión de recursos ... no por la forma en que reaccionas a una excepción de lo contrario :)
No hay forma de "olvidar" f.close()
cuando se usa with
. De esta manera, cumple la misma función que using
en C #.
Feliz codificación.
Para empezar, ayuda a prevenir el problema que ha introducido en su try ... finally ...
ejemplo.
La forma en que lo ha estructurado, si se lanza una excepción al intentar abrir el archivo, nunca vinculará un archivo abierto con el nombre f
, lo que NameError
lugar a un NameError
en la cláusula finally
(si f
nunca se ha vinculado dentro del alcance) ) o algo completamente inesperado (si lo tiene).
La estructura correcta (equivalente a with
) es:
f = open(my_file)
try:
do_stuff_that_fails()
finally:
f.close()
(nota: no hay necesidad de una cláusula except
si no tienes nada que hacer allí).
Su segundo ejemplo igualmente está mal, y debería estructurarse como:
try:
f = open(my_file)
try:
do_stuff_that_fails()
except EXPECTED_EXCEPTION_TYPES as e:
do_stuff_when_it_doesnt_work()
finally:
f.close()
except (IOError, OSError) as e:
do_other_stuff_when_it_we_have_file_IO_problems()
El segundo es (como se indica en otra respuesta) que no puede olvidarse de llamar a f.close()
.
Por cierto, el término es "gestión de contexto", no "gestión de recursos": la declaración with
maneja contextos , algunos de los cuales pueden ser recursos, pero otros no. Por ejemplo, también se usa con decimal
para establecer un contexto decimal para un bloque de código en particular.
Finalmente (respondiendo a su comentario a la respuesta anterior) nunca debe confiar en la semántica de refcount para manejar recursos en Python. Jython, IronPython y PyPy tienen una semántica sin refcount, y no hay nada que impida que CPython vaya por el otro lado (aunque es muy poco probable para el futuro inmediato). En un ciclo cerrado (por ejemplo, os.walk
) es muy fácil agotar los identificadores de archivo si el código que se basa en la semántica de refcount se ejecuta en una máquina virtual con un comportamiento diferente.