以下を検討してください。
with open(path, mode) as f:
return [line for line in f if condition]
ファイルは適切に閉じられますか、それともコンテキストマネージャーをreturn
バイパスして使用しますか?
以下を検討してください。
with open(path, mode) as f:
return [line for line in f if condition]
ファイルは適切に閉じられますか、それともコンテキストマネージャーをreturn
バイパスして使用しますか?
回答:
はい、finally
ブロックの後のtry
ブロックのように機能します。つまり、常に実行されます(もちろん、Pythonプロセスが異常な方法で終了しない限り)。
これは、ステートメントの仕様であるPEP-343の例の1つでも言及されてい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).
ただし、言及する価値があるのは、通常は望んでいないブロック内にブロックopen()
全体を配置しないと、呼び出しによってスローされた例外を簡単にキャッチできないことです。with
try..except
Process.terminate()
限り、finally
ステートメントの呼び出しを保証しない数少ない(唯一の?)シナリオの1つです:「exitハンドラーやfinally節などは、実行されました。」
os._exit
は時々使用されます-クリーンアップハンドラーを呼び出さずにPythonプロセスを終了します。
with
ませんが、ブロック内からジェネレータ式を返す場合、ジェネレータが値を生成し続ける限り、保証は保持されますか?何かがそれを参照している限り?del
つまり、ジェネレータオブジェクトを保持する変数に別の値を使用または割り当てる必要がありますか?
ValueError: I/O operation on closed file.
。
はい。
def example(path, mode):
with open(path, mode) as f:
return [line for line in f if condition]
..ほぼ以下と同等です:
def example(path, mode):
f = open(path, mode)
try:
return [line for line in f if condition]
finally:
f.close()
より正確には、__exit__
(例外や戻り値に関係なく)ブロックを終了すると、コンテキストマネージャのメソッドが常に呼び出されます。ファイルオブジェクトの__exit__
メソッドが呼び出すだけf.close()
(たとえば、ここではCPython)
finally
キーロッドから得られる保証を示す興味深い実験は次のとおりdef test(): try: return True; finally: return False
です。
はい。より一般的に__exit__
は、Withステートメントコンテキストマネージャーのメソッドは、コンテキストreturn
内からのイベントで実際に呼び出されます。これは次の方法でテストできます。
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()
出力は次のとおりです。
Entering context.
Returning inside with-statement.
EXITING context.
上記の出力__exit__
は、初期のにもかかわらず呼び出されたことを確認しreturn
ます。そのため、コンテキストマネージャはバイパスされません。
はい、ただし、__exit__
ブロックで何かを実行する必要があるため(バッファのフラッシュなど)、他のケースでは何らかの副作用が発生する可能性があります
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
with
そのtry with except
問題を解決するために追加することができます。編集:言語に追加