Considérer ce qui suit:
with open(path, mode) as f:
return [line for line in f if condition]
Le fichier sera-t-il fermé correctement, ou l'utilisation d'une return
manière ou d'une autre contourne-t-elle le gestionnaire de contexte ?
Considérer ce qui suit:
with open(path, mode) as f:
return [line for line in f if condition]
Le fichier sera-t-il fermé correctement, ou l'utilisation d'une return
manière ou d'une autre contourne-t-elle le gestionnaire de contexte ?
Réponses:
Oui, il agit comme le finally
bloc après un try
bloc, c'est-à-dire qu'il s'exécute toujours (sauf si le processus python se termine de manière inhabituelle bien sûr).
Il est également mentionné dans l'un des exemples de PEP-343 qui est la spécification de la with
déclaration:
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).
Cependant, il convient de mentionner que vous ne pouvez pas facilement détecter les exceptions levées par l' open()
appel sans placer le with
bloc entier dans un try..except
bloc qui n'est généralement pas ce que vous voulez .
Process.terminate()
est l'un des rares (le seul?) Scénario qui ne garantit pas l'appel d'une finally
instruction: "Notez que les gestionnaires de sortie et enfin les clauses, etc., ne seront pas réalisé."
with
bloc, la garantie est-elle valable aussi longtemps que le générateur continue de produire des valeurs? aussi longtemps que quelque chose y fait référence? Est-ce que j'ai besoin d'utiliser del
ou d'attribuer une valeur différente à la variable qui contient l'objet générateur?
ValueError: I/O operation on closed file.
.
Oui.
def example(path, mode):
with open(path, mode) as f:
return [line for line in f if condition]
..est à peu près équivalent à:
def example(path, mode):
f = open(path, mode)
try:
return [line for line in f if condition]
finally:
f.close()
Plus précisément, la __exit__
méthode dans un gestionnaire de contexte est toujours appelée lors de la sortie du bloc (quelles que soient les exceptions, les retours, etc.). La __exit__
méthode de l'objet fichier appelle simplement f.close()
(par exemple ici en CPython )
finally
keywrod est: def test(): try: return True; finally: return False
.
Oui. Plus généralement, la __exit__
méthode d'un With Statement Context Manager sera en effet appelée en cas de return
de l'intérieur du contexte. Cela peut être testé avec les éléments suivants:
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()
La sortie est:
Entering context.
Returning inside with-statement.
EXITING context.
La sortie ci-dessus confirme qu'elle a __exit__
été appelée malgré le début return
. En tant que tel, le gestionnaire de contexte n'est pas contourné.
Oui, mais il peut y avoir des effets secondaires dans d'autres cas, car cela peut faire quelque chose (comme le vidage du tampon) dans le __exit__
bloc
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
pourrait être ajoutéwith
pour résoudre cetry with except
problème. edit: ajouté à la langue