Оператор «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 для выполнения этого диспетчера контекста, выполните следующие действия:

  1. Программа вызывает __init__() для инициализации объекта OpenFile с помощью filename:file_name и file mode:'r'.
  2. Оператор with вызывает __enter__(), чтобы открыть файл test.txt в режиме чтения, вернуть объект aOpenFile в переменную f.
  3. Прочтите «test.txt», напечатайте «Hello World, реализация диспетчера контекста как класса».
  4. Оператор with вызывает __exit__(), чтобы закрыть файл. Три параметра exc_type, exc_val и traceback указывают соответственно: exception_type, exception_value, and trackbackin __exit__(). Если из контекста вышел без исключения, все три аргумента будут None.

Обработка исключений

Если нам нужно обрабатывать исключения, мы можем добавить коды в блок __exit__().

В этом примере оператор with вручную вызвал исключительную ситуацию. Исключение было обработано в __exit__().

Если вы подтверждаете, что исключения были обработаны, вы должны добавить return True в __exit__().

Реализация диспетчера контекста в качестве генератора: contextlib.contextmanager

generators и декоратор contextlib.contextmanager Python предоставляют удобный способ реализации этих протоколов. Если функция генератора украшена contextlib.contextmanagerdecorator, она вернет диспетчер контекста, реализующий необходимые методы __enter__() и __exit__(), а не итератор, созданный функцией генератора без декорирования.

Приведенный выше код Open file переписывается следующим образом:

В этом коде функция open_file является генератором. Мы должны добавить декоратор @contextmanager в начале.

Интерпретатор Python распознает оператор yield в середине определения функции. Код перед оператором yield эквивалентен методу__enter__(). а код после оператора yield эквивалентен методу__exit__().

Вышеупомянутые два метода создания диспетчера контекста функционально одинаковы. Мы видим, что диспетчер контекста, использующий класс, более гибкий и подходит для разработки более крупных систем; менеджер контекста, использующий генератор, более удобен и лаконичен, подходит для малых и средних систем.

Заключение

Диспетчер контекста обычно используется в сценариях, где используются ресурсы, такие как открытие и закрытие файлов, использование блокировок потоков и закрытие подключений к базе данных. Это может гарантировать, что используемые ресурсы высвобождаются быстро и эффективно, повышая безопасность программы.

В Python диспетчер контекста обычно используется с оператором with для упрощения программы.

Спасибо за внимание.