2012-03-27 7 views

risposta

124

Sì, si comporta come il blocco finally dopo un blocco try, vale a dire viene sempre eseguito (a meno che il processo python non termini in modo insolito, ovviamente).

Viene anche menzionato in uno degli esempi di PEP-343, che è la specifica per l'istruzione 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). 

Qualcosa degno di nota è tuttavia, che non si può prendere facilmente le eccezioni sollevate dalla chiamata open() senza mettere l'intero blocco with all'interno di un blocco try..except che di solito non è quello che si desidera.

+7

'else' potrebbe essere aggiunto a' with' per risolvere il problema 'try with except'. modifica: aggiunta alla lingua – rplnt

+7

Non so se è rilevante, ma per quanto ne so 'Process.terminate() 'è uno dei pochi (l'unico?) scenario che non garantisce la chiamata di una istruzione' finally' : * "Si noti che i gestori di uscita e infine le clausole, ecc., Non verranno eseguiti." * –

+0

@RikPoggi ['os._exit'] (https://docs.python.org/library/os.html#os. _exit) a volte viene utilizzato - Esce dal processo Python senza chiamare i gestori di cleanup. –

18

Sì.

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

..è più o meno equivalente a:

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

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

Più precisamente, il metodo __exit__ in un contesto manager è sempre chiamato quando si esce il blocco (a prescindere dalla eccezioni, restituisce ecc). Metodo dell'oggetto file di __exit__ chiama solo f.close() (es here in CPython)

+13

Un esperimento interessante per mostrare la garanzia che si ottiene dal 'keywrod 'è:' def test(): try: return True; infine: restituisci False'. –

4

Più in generale, il metodo di una With Statement Context Manager__exit__ sarà effettivamente chiamato nel caso di return dall'interno del contesto. Questo può essere testato con il seguente:

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() 

L'output è:

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

L'output sopra conferma che __exit__ è stato chiamato nonostante la precoce return. In quanto tale, il gestore del contesto non viene ignorato.

Problemi correlati