Я рекомендую використовувати 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