Folgendes berücksichtigen:
with open(path, mode) as f:
return [line for line in f if condition]
Wird die Datei ordnungsgemäß geschlossen oder wird return
der Kontextmanager irgendwie umgangen ?
Folgendes berücksichtigen:
with open(path, mode) as f:
return [line for line in f if condition]
Wird die Datei ordnungsgemäß geschlossen oder wird return
der Kontextmanager irgendwie umgangen ?
Antworten:
Ja, es verhält sich wie ein finally
Block nach dem anderen try
, dh es wird immer ausgeführt (es sei denn, der Python-Prozess wird natürlich auf ungewöhnliche Weise beendet).
Es wird auch in einem der Beispiele von PEP-343 erwähnt, das die Spezifikation für die with
Aussage ist:
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).
Erwähnenswert ist jedoch, dass Sie Ausnahmen, die durch den open()
Aufruf ausgelöst werden, nicht einfach abfangen können , ohne den gesamten with
Block in einen try..except
Block zu setzen, der normalerweise nicht das ist, was man will.
Process.terminate()
ist es eines der wenigen (einzigen?) Szenarien, die den Aufruf einer finally
Anweisung nicht garantieren : "Beachten Sie, dass Exit-Handler und schließlich Klauseln usw.
with
Block zurückgebe, bleibt die Garantie so lange bestehen, wie der Generator weiterhin Werte liefert? solange irgendetwas darauf verweist? Muss ich del
der Variablen, die das Generatorobjekt enthält, einen anderen Wert verwenden oder einen anderen Wert zuweisen?
ValueError: I/O operation on closed file.
.
Ja.
def example(path, mode):
with open(path, mode) as f:
return [line for line in f if condition]
..ist ziemlich gleichbedeutend mit:
def example(path, mode):
f = open(path, mode)
try:
return [line for line in f if condition]
finally:
f.close()
Genauer gesagt wird die __exit__
Methode in einem Kontextmanager beim Verlassen des Blocks immer aufgerufen (unabhängig von Ausnahmen, Rückgaben usw.). Die __exit__
Methode des Dateiobjekts ruft nur auf f.close()
(z. B. hier in CPython ).
finally
Schlüssel erhalten, ist : def test(): try: return True; finally: return False
.
Ja. Im Allgemeinen wird die __exit__
Methode eines With Statement Context Managers tatsächlich aufgerufen, wenn ein return
Kontext innerhalb des Kontexts angezeigt wird . Dies kann mit folgendem getestet werden:
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()
Die Ausgabe ist:
Entering context.
Returning inside with-statement.
EXITING context.
Die obige Ausgabe bestätigt, dass __exit__
trotz des frühen aufgerufen wurde return
. Daher wird der Kontextmanager nicht umgangen.
Ja, aber in anderen Fällen kann es zu Nebenwirkungen kommen, da im __exit__
Block möglicherweise etwas getan werden sollte (z. B. das Löschen des Puffers)
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
könnte hinzugefügt werdenwith
, um diesestry with except
Problem zu lösen . bearbeiten: zur Sprache hinzugefügt