2012-07-18 31 views
134

No estoy seguro de por qué necesitamos finally en try...except...finally declaraciones. En mi opinión, este bloque de código¿Por qué necesitamos la cláusula "finally" en Python?

try: 
    run_code1() 
except TypeError: 
    run_code2() 
other_code() 

es la misma con éste usando finally:

try: 
    run_code1() 
except TypeError: 
    run_code2() 
finally: 
    other_code() 

Me estoy perdiendo algo?

Respuesta

191

se hace una diferencia si Regreso anticipado:

try: 
    run_code1() 
except TypeError: 
    run_code2() 
    return None # The finally block is run before the method returns 
finally: 
    other_code() 

Compare con 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 produce una excepción en el interior el bloque excepto
  • Si se lanza una excepción en run_code1() pero no es un TypeError.
  • Otras instrucciones de flujo de control como continue y break declaraciones.
+0

intento: # x = Hola + 20 x = 10 + 20 excepto: de impresión 'Estoy en bloque, excepto' x = 20 + 30 otra cosa: de impresión 'Estoy en bloque else' x + = 1 finally: print 'Finalmente x =% s'% (x) –

11

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.

+6

'Finalmente, el código se ejecuta sin importar qué más ocurra ... a menos que haya un ciclo infinito. O un corte de energía. O 'os._exit()'. O ... –

+2

... una segfault. O 'SIGABRT'. –

+2

@Mark En realidad, sys.exit arroja una excepción normal. Pero sí, cualquier cosa que provoque que el proceso finalice inmediatamente significará que no se ejecuta nada más. – Antimony

7

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.

6

En su primer ejemplo, ¿qué ocurre si run_code1() genera una excepción que no es TypeError? ... other_code() no se ejecutará.

Compárelo con la versión finally:: other_code() se garantiza que se ejecutará independientemente de cualquier excepción.

35

Puede usar 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 detecta la excepción. (O si no se captura que específica excepción.)

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 utilizar la instrucción with, pero este tipo de estructura se puede utilizar para otros tipos de recursos .

Unos años más tarde, escribí a blog post sobre un abuso de finally que los lectores pueden encontrar divertido.

3

finally es para definir "acciones de limpieza". La cláusula finally se ejecuta en cualquier caso antes de abandonar la declaración try, ya sea que haya ocurrido una excepción (incluso si no la maneja).

I second @ Byers's example.

2

Finalmente también se puede usar cuando se quiere ejecutar un 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 exactamente 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() 

embargo, la mayoría de las borras de se quejan acerca de la captura demasiado vaga de una excepción. Además, como elegimos solo pass para 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.

1

ejemplo perfecto es la 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) 
1

Como se explica en la documentation, la cláusula finally pretende definir acciones de limpieza que deben ser ejecutadas en todas las circunstancias.

Si finally está presente, especifica un controlador de "limpieza". Se ejecuta la cláusula try , 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. Se ejecuta la cláusula finally. Si hay una excepción guardada, se vuelve a generar al final de la finally cláusula.

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 se puede ver, la cláusula finally se ejecuta en cualquier caso. El TypeError generado al dividir dos cadenas no se trata mediante 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.

1

Para agregar a las otras respuestas anteriores, la cláusula finally se ejecuta sin importar qué mientras que la cláusula else se ejecuta solo si no se produjo una excepción.

Por ejemplo, escribir en un archivo sin excepciones se emitiría 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, la El código generará lo siguiente, (tenga en cuenta que se produce un error deliberado manteniendo el archivo solo anuncios

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.

Cuestiones relacionadas