Сообщить об ошибке.

Класс ExitStack() модуля contextlib в Python

Стек обратных вызовов для менеджера контекста

Синтаксис:

import contextlib

stack = contextlib.ExitStack()

Параметры:

  • нет.

Возвращаемое значение:

Описание:

Класс ExitStack() модуля contextlib менеджер контекста, разработанный для упрощения программного комбинирования других менеджеров контекста и функций очистки, особенно тех, которые являются необязательными или управляются входными данными иным образом.

Например, набор файлов может быть легко обработан в одном выражении with следующим образом:

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # Все открытые файлы будут автоматически закрыты в 
    # конце оператора `with`, даже если попытки открыть 
    # файлы позже в списке вызовут исключение

Каждый экземпляр поддерживает стек зарегистрированных обратных вызовов, которые вызываются в порядке обратном регистрации, когда экземпляр закрывается явно или неявно в конце оператора with. Обратите внимание, что когда экземпляр стека контекста удаляется сборщиком мусора, то обратные вызовы вызываются явно.

Эта модель использует стек, так что контекст-менеджеры, которые получают свои ресурсы в методе __init__(), например файловые объекты, обрабатываются правильно.

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

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

Методы объекта ExitStack.


stack.enter_context(cm):

Метод stack.enter_context() входит в новый менеджер контекста cm и добавляет его метод __exit__() в стек обратного вызова. Возвращаемое значение является результатом собственного метода __enter__() менеджера контекста.

Эти менеджеры контекста могут подавлять исключения как обычно, если они используются непосредственно как часть оператора with.

Изменено в Python 3.11: вызывает TypeError вместо AttributeError, если аргумент cm не является менеджером контекста.

stack.push(exit):

Метод stack.push() добавляет метод __exit__() менеджера контекста в стек обратного вызова.

Поскольку метод __enter__() не вызывается, то метод stack.push() можно использовать для покрытия части реализации __enter__() собственным методом __exit__() менеджера контекста.

Если передан объект, который не является менеджером контекста, то этот метод предполагает, что это обратный вызов с той же сигнатурой, что и метод __exit__() менеджера контекста, и добавляет его непосредственно в стек обратного вызова.

Возвращая истинные значения, эти обратные вызовы могут подавлять исключения точно так же, как это делает метод менеджера контекста __exit__().

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

stack.callback(callback, *args, **kwds):

Метод stack.callback() принимает произвольную функцию обратного вызова callback и аргументы *args, **kwds и добавляет ее в стек обратного вызова.

В отличие от других методов, обратные вызовы, добавленные таким образом, не могут подавлять исключения, поскольку они никогда не передают сведения об исключении.

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

stack.pop_all():

Метод stack.pop_all() переносит стек обратного вызова в новый экземпляр ExitStack и возвращает его. Эта операция не вызывает никаких обратных вызовов - вместо этого они теперь будут вызываться при закрытии нового стека явно или неявно в конце оператора with.

Например, группа файлов может быть открыта как операция "все или ничего" следующим образом:

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # Определим метод close, но пока вызывайте его не будем.
    close_files = stack.pop_all().close
    # Если открыть какой-либо файл не удается, то все ранее 
    # открытые файлы будут закрыты автоматически. 
    # Если все файлы открыты успешно, они останутся 
    # открытыми даже после завершения оператора `with`.
    # Чтобы закрыть все файлы, потом необходимо явно 
    # вызвать метод close_files().

stack.close():

Метод stack.close() немедленно раскручивает стек обратного вызова, вызывая обратные вызовы в порядке, обратном регистрации.

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