Я рекомендую використовувати withоператор Python для управління ресурсами, які потрібно очистити. Проблема використання явного close()висловлювання полягає в тому, що вам доведеться турбуватися про те, що люди взагалі забули його зателефонувати або забули розмістити його в finallyблоці, щоб запобігти витоку ресурсів, коли відбувається виняток.
Щоб використовувати withоператор, створіть клас за допомогою таких методів:
def __enter__(self)
def __exit__(self, exc_type, exc_value, traceback)
У наведеному вище прикладі ви б використовували
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)
Потім, коли хтось захотів використати ваш клас, він зробив би наступне:
with Package() as package_obj:
# use package_obj
Змінна package_obj буде екземпляром типу Package (це значення, повернене __enter__методом). Його __exit__метод буде автоматично викликаний, незалежно від того, відбудеться виняток чи ні.
Можна навіть зробити такий підхід на крок далі. У наведеному вище прикладі хтось все-таки може створити пакет, використовуючи його конструктор, не використовуючи withпункт. Ви не хочете, щоб це сталося. Ви можете виправити це, створивши клас PackageResource, який визначає __enter__та __exit__методи. Тоді клас Package буде визначений строго всередині __enter__методу та повернутий. Таким чином, абонент ніколи не міг створити екземпляр класу Package без використання withоператора:
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()
Ви використовуєте це наступним чином:
with PackageResource() as package_obj:
# use package_obj