Risposte:
Sì, si comporta come il finally
blocco dopo un try
blocco, ovvero viene sempre eseguito (a meno che il processo python non termini in modo insolito, ovviamente).
È anche menzionato in uno degli esempi di PEP-343 che è la specifica per l' with
affermazione:
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 che vale la pena ricordare è che non è possibile catturare facilmente le eccezioni generate dalla open()
chiamata senza inserire l'intero with
blocco all'interno di un try..except
blocco che di solito non è quello che si desidera.
Process.terminate()
è uno dei pochi (l'unico?) Scenario che non garantisce la chiamata di una finally
dichiarazione: "Nota che i gestori di uscita e infine le clausole, ecc., Non lo saranno eseguito."
with
blocco, la garanzia rimane valida finché il generatore continua a produrre valori? fino a quando qualcosa lo fa riferimento? Cioè del
devo usare o assegnare un valore diverso alla variabile che contiene l'oggetto generatore?
ValueError: I/O operation on closed file.
.
Sì.
def example(path, mode):
with open(path, mode) as f:
return [line for line in f if condition]
..è praticamente 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 __exit__
metodo in un gestore di contesto viene sempre chiamato all'uscita dal blocco (indipendentemente da eccezioni, ritorni ecc.). Il __exit__
metodo dell'oggetto file chiama solo f.close()
(ad es. Qui in CPython )
finally
keywrod è: def test(): try: return True; finally: return False
.
Sì. Più in generale, il __exit__
metodo di un Gestore di contesto con dichiarazione verrà effettivamente chiamato in caso di return
all'interno del contesto. Questo può essere testato con quanto segue:
class MyResource:
def __enter__(self):
print('Entering context.')
return self
def __exit__(self, *exc):
print('EXITING context.')
def fun():
with MyResource():
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 i primi return
. Pertanto, il gestore del contesto non viene ignorato.
Sì, ma potrebbe esserci qualche effetto collaterale in altri casi, perché potrebbe fare qualcosa (come il flushing buffer) in __exit__
blocco
import gzip
import io
def test(data):
out = io.BytesIO()
with gzip.GzipFile(fileobj=out, mode="wb") as f:
f.write(data)
return out.getvalue()
def test1(data):
out = io.BytesIO()
with gzip.GzipFile(fileobj=out, mode="wb") as f:
f.write(data)
return out.getvalue()
print(test(b"test"), test1(b"test"))
# b'\x1f\x8b\x08\x00\x95\x1b\xb3[\x02\xff' b'\x1f\x8b\x08\x00\x95\x1b\xb3[\x02\xff+I-.\x01\x00\x0c~\x7f\xd8\x04\x00\x00\x00'
else
potrebbe essere aggiuntowith
per risolvere queltry with except
problema. modifica: aggiunto alla lingua