Оператор «with» и менеджеры контекста в Python, два способа реализации протокола управления контекстом
Как программисты, мы обычно используем try/expect/finally
шаблоны для обработки операций управления ресурсами, таких как открытие файла, подключение к базе данных и получение блокировки.
В Python мы можем использовать оператор with и диспетчер контекста, чтобы упростить эти операции.
В этой статье будет рассказано, как использовать оператор «с» и что такое диспетчер контекста.
Например:
Мы знаем это во многих языках программирования (например, Java), когда работаем с системными ресурсами, например, читаем файлы. Всем нам нужно использовать try/expect/finally
, чтобы гарантировать правильное использование ресурсов, обнаружение ошибок и своевременное высвобождение ресурсов.
В следующем коде показано использование try/finally
для чтения файла в Python.
В python мы также можем использовать оператор with
, чтобы упростить приведенный выше код в две строки.
Оператор with
Оператор with
используется для обертывания выполнения блока методами, определенными диспетчером контекста (мы поговорим об этом позже). Это позволяет инкапсулировать общие try/expect/finally
шаблоны использования для удобного повторного использования.
Базы данных:
Здесь with
используется для запроса базы данных и возврата ее содержимого.
Замки:
В этом примере в операторе with
используется locks
.
TensorFlow:
Использование оператора with
в Tensorflow.
Зачем использовать with
для упрощения этих операций? Поскольку эти операции реализуют API диспетчера контекста и совместимы с оператором with
.
Менеджер контекста
менеджер контекста - это объект, который определяет контекст времени выполнения, который должен быть установлен при выполнении оператора with
.
Диспетчер контекста обрабатывает вход и выход из желаемого контекста времени выполнения для выполнения блочного кода. Менеджеры контекста обычно вызываются с помощью оператора with
.
С менеджерами контекста утверждения
with
синтаксис:
with EXPR as VAR: BLOCK
with
иas
- ключевые слова.EXPR
- произвольное выражение, менеджер контекста.VAR
- это единственная цель назначения.
Реализация диспетчера контекста
Есть два способа реализовать протокол управления контекстом в Python: определяемые пользователем классы и генераторы.
Реализация диспетчера контекста как пользовательского класса
Чтобы реализовать диспетчер контекста, мы определяем класс, содержащий методы __enter__()
и __exit__()
.
Например, мы определили открытый файловый менеджер.
Когда мы используем оператор with
для выполнения этого диспетчера контекста, выполните следующие действия:
- Программа вызывает
__init__()
для инициализации объектаOpenFile
с помощьюfilename:file_name
иfile mode:'r'
. - Оператор
with
вызывает__enter__()
, чтобы открыть файл test.txt в режиме чтения, вернуть объект aOpenFile
в переменнуюf
. - Прочтите «test.txt», напечатайте «Hello World, реализация диспетчера контекста как класса».
- Оператор
with
вызывает__exit__()
, чтобы закрыть файл. Три параметраexc_type
,exc_val
иtraceback
указывают соответственно:exception_type, exception_value, and trackback
in__exit__()
. Если из контекста вышел без исключения, все три аргумента будутNone
.
Обработка исключений
Если нам нужно обрабатывать исключения, мы можем добавить коды в блок __exit__()
.
В этом примере оператор with
вручную вызвал исключительную ситуацию. Исключение было обработано в __exit__()
.
Если вы подтверждаете, что исключения были обработаны, вы должны добавить return True
в __exit__()
.
Реализация диспетчера контекста в качестве генератора: contextlib.contextmanager
generators
и декоратор contextlib.contextmanager
Python предоставляют удобный способ реализации этих протоколов. Если функция генератора украшена contextlib.contextmanager
decorator, она вернет диспетчер контекста, реализующий необходимые методы __enter__()
и __exit__()
, а не итератор, созданный функцией генератора без декорирования.
Приведенный выше код Open file
переписывается следующим образом:
В этом коде функция open_file
является генератором. Мы должны добавить декоратор @contextmanager
в начале.
Интерпретатор Python распознает оператор yield
в середине определения функции. Код перед оператором yield
эквивалентен методу__enter__()
. а код после оператора yield
эквивалентен методу__exit__()
.
Вышеупомянутые два метода создания диспетчера контекста функционально одинаковы. Мы видим, что диспетчер контекста, использующий класс, более гибкий и подходит для разработки более крупных систем; менеджер контекста, использующий генератор, более удобен и лаконичен, подходит для малых и средних систем.
Заключение
Диспетчер контекста обычно используется в сценариях, где используются ресурсы, такие как открытие и закрытие файлов, использование блокировок потоков и закрытие подключений к базе данных. Это может гарантировать, что используемые ресурсы высвобождаются быстро и эффективно, повышая безопасность программы.
В Python диспетчер контекста обычно используется с оператором with
для упрощения программы.
Спасибо за внимание.