Tôi khuyên bạn nên sử dụng with
câu lệnh của Python để quản lý các tài nguyên cần được dọn sạch. Vấn đề với việc sử dụng một close()
tuyên bố rõ ràng là bạn phải lo lắng về việc mọi người quên gọi nó hoặc quên đặt nó trong một finally
khối để ngăn chặn rò rỉ tài nguyên khi xảy ra ngoại lệ.
Để sử dụng with
câu lệnh, hãy tạo một lớp với các phương thức sau:
def __enter__(self)
def __exit__(self, exc_type, exc_value, traceback)
Trong ví dụ của bạn ở trên, bạn sẽ sử dụng
class Package:
def __init__(self):
self.files = []
def __enter__(self):
return self
# ...
def __exit__(self, exc_type, exc_value, traceback):
for file in self.files:
os.unlink(file)
Sau đó, khi ai đó muốn sử dụng lớp của bạn, họ sẽ làm như sau:
with Package() as package_obj:
# use package_obj
Biến gói_obj sẽ là một thể hiện của kiểu Gói (đó là giá trị được __enter__
phương thức trả về ). __exit__
Phương thức của nó sẽ tự động được gọi, bất kể có xảy ra ngoại lệ hay không.
Bạn thậm chí có thể đưa phương pháp này một bước xa hơn. Trong ví dụ trên, ai đó vẫn có thể khởi tạo Gói bằng cách sử dụng hàm tạo của nó mà không cần sử dụng with
mệnh đề. Bạn không muốn điều đó xảy ra. Bạn có thể khắc phục điều này bằng cách tạo một lớp PackageResource xác định các phương thức __enter__
và __exit__
. Sau đó, lớp Gói sẽ được định nghĩa đúng trong __enter__
phương thức và được trả về. Theo cách đó, người gọi không bao giờ có thể khởi tạo lớp Gói mà không sử dụng with
câu lệnh:
class PackageResource:
def __enter__(self):
class Package:
...
self.package_obj = Package()
return self.package_obj
def __exit__(self, exc_type, exc_value, traceback):
self.package_obj.cleanup()
Bạn sẽ sử dụng như sau:
with PackageResource() as package_obj:
# use package_obj