Hãy xem xét những điều sau đây:
with open(path, mode) as f:
return [line for line in f if condition]
Tập tin sẽ được đóng đúng cách, hoặc bằng return
cách nào đó bỏ qua trình quản lý bối cảnh ?
Hãy xem xét những điều sau đây:
with open(path, mode) as f:
return [line for line in f if condition]
Tập tin sẽ được đóng đúng cách, hoặc bằng return
cách nào đó bỏ qua trình quản lý bối cảnh ?
Câu trả lời:
Vâng, nó hoạt động giống như finally
khối sau một try
khối, tức là nó luôn luôn thực thi (trừ khi quá trình python kết thúc theo một cách khác thường).
Nó cũng được đề cập trong một trong các ví dụ về PEP-343 là đặc điểm kỹ thuật cho with
tuyên bố:
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).
Tuy nhiên, một điều đáng nói là bạn không thể dễ dàng bắt gặp các ngoại lệ do open()
cuộc gọi ném mà không đặt toàn bộ with
khối bên trong một try..except
khối thường không phải là thứ mà người ta muốn.
Process.terminate()
là một trong số ít kịch bản (duy nhất?) Không đảm bảo cuộc gọi của một finally
tuyên bố: "Lưu ý rằng các trình xử lý thoát và cuối cùng là mệnh đề, v.v., sẽ không Thực thi."
with
khối, liệu bảo đảm có giữ được miễn là trình tạo giữ các giá trị không? miễn là có gì tham khảo nó? Tức là tôi cần sử dụng del
hoặc gán một giá trị khác cho biến chứa đối tượng trình tạo?
ValueError: I/O operation on closed file.
.
Đúng.
def example(path, mode):
with open(path, mode) as f:
return [line for line in f if condition]
.. nó khá nhiều tương đương với:
def example(path, mode):
f = open(path, mode)
try:
return [line for line in f if condition]
finally:
f.close()
Chính xác hơn, __exit__
phương thức trong trình quản lý bối cảnh luôn được gọi khi thoát khỏi khối (bất kể ngoại lệ, trả về, v.v.). __exit__
Phương thức của đối tượng tệp chỉ gọi f.close()
(ví dụ ở đây trong CPython )
finally
keywrod là : def test(): try: return True; finally: return False
.
Đúng. Tổng quát hơn, __exit__
phương thức của Trình quản lý bối cảnh với câu lệnh thực sự sẽ được gọi trong trường hợp return
từ bên trong bối cảnh. Điều này có thể được kiểm tra với những điều sau đây:
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()
Đầu ra là:
Entering context.
Returning inside with-statement.
EXITING context.
Đầu ra ở trên xác nhận rằng __exit__
đã được gọi mặc dù sớm return
. Như vậy, người quản lý bối cảnh không được bỏ qua.
Có, nhưng có thể có một số tác dụng phụ trong các trường hợp khác, bởi vì nó có thể làm một cái gì đó (như bộ đệm xả) trong __exit__
khối
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
có thể được thêm vàowith
để giải quyếttry with except
vấn đề đó . chỉnh sửa: thêm vào ngôn ngữ