print - try catch python example
¿Por qué necesitamos la cláusula "finalmente" en Python? (11)
No estoy seguro de por qué necesitamos finally
try...except...finally
declaraciones. En mi opinión, este bloque de código
try:
run_code1()
except TypeError:
run_code2()
other_code()
es lo mismo con este usando finally
:
try:
run_code1()
except TypeError:
run_code2()
finally:
other_code()
¿Me estoy perdiendo de algo?
Como se explica en la documentation , la cláusula finally
está destinada a definir acciones de limpieza que deben ejecutarse bajo cualquier circunstancia .
Si
finally
está presente, especifica un controlador de ''limpieza''. La cláusulatry
se ejecuta, incluidas las cláusulasexcept
yelse
. Si se produce una excepción en cualquiera de las cláusulas y no se maneja, la excepción se guarda temporalmente. La cláusulafinally
se ejecuta. Si hay una excepción guardada, se vuelve a subir al final de la cláusulafinally
.
Un ejemplo:
>>> def divide(x, y):
... try:
... result = x / y
... except ZeroDivisionError:
... print("division by zero!")
... else:
... print("result is", result)
... finally:
... print("executing finally clause")
...
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: ''str'' and ''str''
Como puede ver, la cláusula finally
se ejecuta en cualquier caso. El TypeError
generado al dividir dos cadenas no es manejado por la cláusula except
y, por lo tanto, se vuelve a generar después de que se haya ejecutado la cláusula finally
.
En aplicaciones del mundo real, la cláusula finally es útil para liberar recursos externos (como archivos o conexiones de red), independientemente de si el uso del recurso fue exitoso.
El ejemplo perfecto es el siguiente:
try:
#x = Hello + 20
x = 10 + 20
except:
print ''I am in except block''
x = 20 + 30
else:
print ''I am in else block''
x += 1
finally:
print ''Finally x = %s'' %(x)
Ellos no son equivalentes. Finalmente, el código se ejecuta sin importar qué más ocurra. Es útil para el código de limpieza que debe ejecutarse.
En su primer ejemplo, ¿qué sucede si run_code1()
genera una excepción que no es TypeError
? ... other_code()
no se ejecutará.
Compare eso con la versión finally:
version: other_code()
se garantiza que se ejecutará independientemente de cualquier excepción que se plantee.
Hace una diferencia si regresas temprano:
try:
run_code1()
except TypeError:
run_code2()
return None # The finally block is run before the method returns
finally:
other_code()
Compare esto:
try:
run_code1()
except TypeError:
run_code2()
return None
other_code() # This doesn''t get run if there''s an exception.
Otras situaciones que pueden causar diferencias:
- Si se lanza una excepción dentro del bloque excepto.
- Si se lanza una excepción en
run_code1()
pero no es unTypeError
. - Otras sentencias de flujo de control tales como declaraciones de
continue
ybreak
.
Los bloques de código no son equivalentes. La cláusula finally
también se ejecutará si run_code1()
arroja una excepción que no sea TypeError
, o si run_code2()
arroja una excepción, mientras que other_code()
en la primera versión no se ejecutará en estos casos.
Para agregar a las otras respuestas anteriores, la cláusula finally
ejecuta sin importar qué, mientras que la cláusula else
ejecuta solo si no se generó una excepción.
Por ejemplo, escribir en un archivo sin excepciones dará como resultado lo siguiente:
file = open(''test.txt'', ''w'')
try:
file.write("Testing.")
print("Writing to file.")
except IOError:
print("Could not write to file.")
else:
print("Write successful.")
finally:
file.close()
print("File closed.")
SALIDA:
Writing to file.
Write successful.
File closed.
Si hay una excepción, el código dará como resultado lo siguiente (tenga en cuenta que se produce un error deliberado al mantener el archivo como de solo lectura).
file = open(''test.txt'', ''r'')
try:
file.write("Testing.")
print("Writing to file.")
except IOError:
print("Could not write to file.")
else:
print("Write successful.")
finally:
file.close()
print("File closed.")
SALIDA:
Could not write to file.
File closed.
Podemos ver que la cláusula finally
ejecuta independientemente de una excepción. Espero que esto ayude.
Por último, también se puede usar cuando desee ejecutar código "opcional" antes de ejecutar el código para su trabajo principal y ese código opcional puede fallar por varias razones.
En el siguiente ejemplo, no sabemos con precisión qué tipo de excepciones podría arrojar store_some_debug_info
.
Podríamos correr:
try:
store_some_debug_info()
except Exception:
pass
do_something_really_important()
Pero la mayoría de los borrachitos se quejarán de que son demasiado vagos para hacer una excepción. Además, como optamos por pass
errores, el bloque except
realmente no agrega valor.
try:
store_some_debug_info()
finally:
do_something_really_important()
El código anterior tiene el mismo efecto que el primer bloque de código, pero es más conciso.
Puede usarlo finally
para asegurarse de que los archivos o recursos se cierren o se liberen independientemente de si se produce una excepción, incluso si no se detecta la excepción. (O si no captas esa excepción específica )
myfile = open("test.txt", "w")
try:
myfile.write("the Answer is: ")
myfile.write(42) # raises TypeError, which will be propagated to caller
finally:
myfile.close() # will be executed before TypeError is propagated
En este ejemplo, sería mejor usar la instrucción with
, pero este tipo de estructura se puede usar para otros tipos de recursos.
Unos años más tarde, escribí una entrada en el blog sobre un abuso de finally
que los lectores pueden encontrar divertido.
Utilizar Delphi profesionalmente durante algunos años me enseñó a proteger mis rutinas de limpieza utilizando finalmente. Delphi prácticamente impone el uso de, finalmente, limpiar los recursos creados antes del bloque try, para que no se produzca una pérdida de memoria. Así es también como funcionan Java, Python y Ruby.
resource = create_resource
try:
use resource
finally:
resource.cleanup
y el recurso se limpiará independientemente de lo que haga entre el intento y el final. Además, no se limpiará si la ejecución nunca llega al bloque try
. (es decir, create_resource
arroja una excepción) Hace que su código sea "excepción segura".
En cuanto a por qué realmente necesitas un bloqueo final, no todos los idiomas lo hacen. En C ++, ha llamado automáticamente a los destructores que imponen la limpieza cuando una excepción desenrolla la pila. Creo que esto es un paso adelante en la dirección de un código más limpio en comparación con intentar ... finalmente idiomas.
{
type object1;
smart_pointer<type> object1(new type());
} // destructors are automagically called here in LIFO order so no finally required.
finally
es para definir "acciones de limpieza" . La cláusula finally
se ejecuta en cualquier caso antes de abandonar la instrucción try
, ya sea que haya ocurrido una excepción (incluso si no la manejas).
Yo segundo @ el ejemplo de Byers.