Aşağıdakileri göz önünde bulundur:
with open(path, mode) as f:
return [line for line in f if condition]
Dosya düzgün bir şekilde kapatılacak mı yoksa bir return
şekilde içerik yöneticisini atlıyor mu?
Aşağıdakileri göz önünde bulundur:
with open(path, mode) as f:
return [line for line in f if condition]
Dosya düzgün bir şekilde kapatılacak mı yoksa bir return
şekilde içerik yöneticisini atlıyor mu?
Yanıtlar:
Evet, bir finally
bloktan sonra blok gibi davranır try
, yani her zaman yürütülür (python işlemi alışılmadık bir şekilde sona ermediği sürece).
Ayrıca, açıklama için şartname olan PEP-343'ün örneklerinden birinde belirtilmiştir 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).
Bununla birlikte, kayda değer bir şey open()
, tüm with
bloğu bir try..except
bloğun içine koymadan çağrı tarafından atılan istisnaları kolayca yakalayamayacağınızdır ;
Process.terminate()
göre bir finally
ifadenin çağrısını garanti etmeyen birkaç (tek?) Senaryodan biri : "Çıkış işleyicileri ve nihayet hükümler, vb. idam."
with
blok içinde bir jeneratör ifadesi döndürürsem , jeneratör değerleri vermeye devam ettiği sürece garanti geçerli olur mu? bir şey referans verdiği sürece? Yani del
jeneratör nesnesini tutan değişkene farklı bir değer kullanmalı mıyım?
ValueError: I/O operation on closed file.
.
Evet.
def example(path, mode):
with open(path, mode) as f:
return [line for line in f if condition]
.. hemen hemen eşdeğerdir:
def example(path, mode):
f = open(path, mode)
try:
return [line for line in f if condition]
finally:
f.close()
Daha doğrusu, __exit__
içerik yöneticisindeki yöntem her zaman bloktan çıkılırken çağrılır (istisnalar, iadeler vb. Ne olursa olsun). Dosya nesnesinin __exit__
yöntemi sadece çağırıyor f.close()
(örneğin, burada CPython'da )
finally
keywrod geçerli: def test(): try: return True; finally: return False
.
Evet. Daha genel olarak, Deyim İçeren Bağlam Yöneticisinin__exit__
yöntemi gerçekten bağlam içinden bir durumunda çağrılır . Bu aşağıdakilerle test edilebilir: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()
Çıktı:
Entering context.
Returning inside with-statement.
EXITING context.
Yukarıdaki çıktı __exit__
, erken olmasına rağmen çağrıldığını doğrulamaktadır return
. Bu nedenle, bağlam yöneticisi atlanmaz.
Evet, ancak diğer durumlarda bazı yan etkiler olabilir, çünkü __exit__
blokta bir şey (yıkama tamponu gibi) yapmalıdır.
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
butry with except
sorunu çözmek için eklenebilir . düzenleme: dile eklendi