Менеджер контекста Python

PythonBeginner
Практиковаться сейчас

Введение

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

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

Оператор with

На этом шаге вы узнаете, как использовать инструкцию with с менеджерами контекста, такими как файловые объекты. Менеджер контекста — это объект, который уведомляется о начале и конце контекста (блока кода). Инструкция with автоматически управляет этим процессом уведомления.

Например, файловые объекты являются менеджерами контекста. Когда блок with завершается, файловый объект закрывается автоматически, даже если внутри блока произошли ошибки. Это предотвращает потерю данных и утечки ресурсов.

Примечание: Если вы не знакомы с использованием WebIDE (похожего на VS Code), пожалуйста, изучите это в этой лаборатории.

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

## Мы создадим файл для демонстрации инструкции 'with'.
## Сначала давайте запишем некоторое содержимое в файл.
with open('my_file.txt', 'w') as f:
    f.write('This is a test file.')

## Теперь давайте прочитаем его обратно, используя менеджер контекста.
## Файл автоматически закрывается при выходе из блока 'with'.
with open('my_file.txt') as f:
    file_contents = f.read()
    print(file_contents)

## Файл автоматически закрывается здесь, даже если произошла ошибка.
print("\nFile has been read and closed.")

Теперь запустите скрипт из терминала, чтобы увидеть вывод.

python3 main.py

Вы должны увидеть следующий вывод, подтверждающий, что файл был успешно записан и прочитан. Инструкция with гарантирует, что my_file.txt будет корректно закрыт после операций записи и чтения.

This is a test file.

File has been read and closed.

Использование инструкции with является рекомендуемым способом управления ресурсами, такими как файлы или сетевые соединения, поскольку это делает ваш код более чистым и безопасным.

Написание собственного менеджера контекста

На этом шаге вы узнаете, как создать собственный менеджер контекста с помощью генераторной функции и декоратора @contextlib.contextmanager. Это краткий способ создания простых менеджеров контекста.

Код перед оператором yield выполняется при входе в блок with (логика настройки), а код после оператора yield выполняется при выходе из него (логика очистки). Значение, которое передается через yield, может быть присвоено переменной с помощью ключевого слова as в операторе with.

Откройте файл function_cm.py в проводнике файлов. Скопируйте следующий код в этот файл.

## Менеджер контекста на основе функции с использованием декоратора contextlib
import contextlib

@contextlib.contextmanager
def context_manager(num):
    print('Enter')  ## Код перед yield выполняется при __enter__
    yield num + 1   ## Значение, переданное через yield, становится переменной 'cm'
    print('Exit')    ## Код после yield выполняется при __exit__

with context_manager(2) as cm:  ## cm получает значение, переданное через yield (3)
    print('Right in the middle with cm = {}'.format(cm))

Теперь выполните скрипт в терминале.

python3 function_cm.py

Вы увидите следующий вывод. Обратите внимание на порядок выполнения: сначала выполняется код перед yield, затем код внутри блока with, и, наконец, код после yield.

Enter
Right in the middle with cm = 3
Exit

Этот подход очень полезен для создания временных контекстов, таких как настройка и закрытие соединения с базой данных или временное изменение настройки.

Менеджер контекста на основе класса

На этом шаге вы реализуете менеджер контекста в виде класса. Этот подход предоставляет больше контроля и подходит для более сложных сценариев. Чтобы создать менеджер контекста на основе класса, необходимо определить два специальных метода: __enter__ и __exit__.

  • __enter__: Этот метод вызывается при входе в оператор with. Он должен выполнять логику настройки (setup logic). Его возвращаемое значение присваивается переменной после as, если она указана.
  • __exit__: Этот метод вызывается при выходе из блока with, как в случае нормального завершения, так и при возникновении исключения. Он должен выполнять логику очистки (cleanup logic).

Давайте создадим такой менеджер. Откройте файл class_cm.py и скопируйте в него следующий код.

## Менеджер контекста на основе класса: реализация методов __enter__ и __exit__
class ContextManager:
    def __enter__(self, *args, **kwargs):  ## Вызывается при входе в блок 'with'
        print("--enter--")
        return self  ## Может вернуть объект для использования в качестве переменной 'as'

    def __exit__(self, *args):  ## Вызывается при выходе из блока 'with'
        print("--exit--")

with ContextManager():  ## Вызывает __enter__, затем __exit__ по завершении
    print("test")

Запустите скрипт из терминала.

python3 class_cm.py

Вывод демонстрирует поток управления. Сначала вызывается метод __enter__, затем выполняется код внутри блока with, и, наконец, вызывается метод __exit__ для очистки.

--enter--
test
--exit--

Подход на основе классов является мощным, поскольку он позволяет инкапсулировать сложную логику настройки и завершения работы в едином, многократно используемом объекте.

Резюме

Поздравляем с завершением лабораторной работы! Вы узнали, как эффективно управлять ресурсами в Python с помощью менеджеров контекста.

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

  • Подход на основе функции с декоратором @contextlib.contextmanager, который отлично подходит для простых задач настройки и очистки.
  • Подход на основе класса путем реализации методов __enter__ и __exit__, который идеален для более сложного управления ресурсами.

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