2012-03-27 8 views

Respuesta

124

Sí, actúa como el bloque finally después de un bloque try, es decir, siempre se ejecuta (a menos que el proceso de pitón termine de una manera inusual, por supuesto).

También se menciona en uno de los ejemplos de PEP-343 que es la especificación de la declaración with:

with locked(myLock): 
    # Code here executes with myLock held. The lock is 
    # guaranteed to be released when the block is left (even 
    # if via return or by an uncaught exception). 

Algo digno de mencionar es, sin embargo, que no se puede coger fácilmente las excepciones producidas por la llamada open() sin poner todo el bloque with dentro de un bloque try..except que generalmente no es lo que uno quiere.

+7

'else' podría agregarse a' with' para resolver ese problema 'try with except'. editar: agregado al lenguaje – rplnt

+7

No sé si es relevante, pero que yo sepa 'Process.terminate()' es uno de los pocos (¿el único?) escenario que no garantiza la invocación de una sentencia 'finally' : * "Tenga en cuenta que los manejadores de salida y finalmente las cláusulas, etc., no se ejecutarán." * –

+0

@RikPoggi ['os._exit'] (https://docs.python.org/library/os.html#os. _exit) a veces se utiliza: sale del proceso de Python sin llamar a los controladores de limpieza. –

18

Sí.

def example(path, mode): 
    with open(path, mode) as f: 
     return [line for line in f if condition] 

..es más o menos equivalente a:

def example(path, mode): 
    f = open(path, mode) 

    try: 
     return [line for line in f if condition] 
    finally: 
     f.close() 

Más exactamente, el método __exit__ en un gestor de contexto siempre se llama al salir del bloque (independientemente de excepciones, devuelve etc). El método del objeto de archivo __exit__ sólo llama f.close() (por ejemplo here in CPython)

+13

Un experimento interesante para mostrar la garantía que obtienes de la clave 'finally' es:' def test(): try: return True; finalmente: return False'. –

4

De manera más general, el método de un With Statement Context Manager__exit__ de hecho se llamará en caso de un return desde el interior del marco. Esto puede ser probado con los siguientes:

class Resource: 
    def __enter__(self): 
     print('Entering context.') 
     return self 

    def __exit__(self, *exc): 
     print('Exiting context.') 

def fun(): 
    with Resource(): 
     print('Returning inside with-statement.') 
     return 
    print('Returning outside with-statement.') 

fun() 

La salida es:

Entering context. 
Returning inside with-statement. 
Exiting context. 

La salida anterior confirma que __exit__ se llamaba a pesar de la temprana return. Como tal, el administrador de contexto no se pasa por alto.

Cuestiones relacionadas