with
операторы или менеджеры контекста существуют для помощи с ресурсами (хотя могут использоваться для гораздо большего).
Допустим, вы открыли файл для записи:
f = open(path, "w")
Теперь у вас есть дескриптор открытого файла.Во время обработки вашего файла никакая другая программа не может писать в него.Чтобы позволить другим программам писать в него, вы должны закрыть дескриптор файла:
f.close()
Но перед закрытием файла произошла ошибка:
f = open(path, "w")
data = 3/0 # Tried dividing by zero. Raised ZeroDivisionError
f.write(data)
f.close()
Что произойдет сейчас, так эточто функция или вся программа завершат работу, оставив ваш файл с открытой ручкой.(CPython очищает дескрипторы при завершении и дескрипторы освобождаются вместе с программой, но вы не должны на это рассчитывать)
Оператор with гарантирует, что, как только вы покинете свой отступ, он закроет дескриптор файла:
with open(path, "w") as f:
data = 3/0 # Tried dividing by zero. Raised ZeroDivisionError
f.write(data)
# In here the file is already closed automatically, no matter what happened.
with
заявления могут быть использованы для многих других вещей.Например: threading.Lock()
lock = threading.Lock()
with lock: # Lock is acquired
do stuff...
# Lock is automatically released.
Почти все, что делается с помощью менеджера контекста, может быть сделано с помощью try: ... finally: ...
, но менеджеры контекста удобнее в использовании, удобнее, удобочитаемее иреализация __enter__
и __exit__
обеспечивает простой в использовании интерфейс.
Создание менеджеров контекста выполняется путем реализации __enter__()
и __exit__()
в обычном классе.
__enter__()
сообщает, что делать при запуске диспетчера контекста, и __exit__()
при наличии диспетчера контекста (дает исключение методу __exit__()
в случае возникновения исключения)
Ярлык для создания менеджеров контекста можно найти в contextlib .Оборачивает генератор как менеджер контекста.