try print pass exceptions example error custom catch all python exception-handling try-finally

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áusula try se ejecuta, incluidas las cláusulas except y else . Si se produce una excepción en cualquiera de las cláusulas y no se maneja, la excepción se guarda temporalmente. La cláusula finally se ejecuta. Si hay una excepción guardada, se vuelve a subir al final de la cláusula finally .

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 un TypeError .
  • Otras sentencias de flujo de control tales como declaraciones de continue y break .

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.