Шаг 150.
Основы языка Python.
Обработка исключений. Инструкция with...as

    На этом шаге мы рассмотрим назначение и примеры использования этой инструкции.

    Язык Python поддерживает протокол менеджеров контекста. Этот протокол гарантирует выполнение завершающих действий (например, закрытие файла) вне зависимости от того, произошло исключение внутри блока кода или нет.

    Для работы с протоколом предназначена инструкция with...as. Инструкция имеет следующий формат:

  with <Выражение1> [ as <Переменная>][, ...,
       <ВыражениеN> [ as <Переменная>]]: 
    <Блок, в котором перехватываем исключения>

    Вначале вычисляется <Выражение1>, которое должно возвращать объект, поддерживающий протокол. Этот объект должен иметь два метода: __enter()__ и __exit__(). Метод __enter__() вызывается после создания объекта. Значение, возвращаемое этим методом, присваивается переменной, указанной после ключевого слова as. Если переменная не указана, возвращаемое значение игнорируется. Формат метода __enter__():

  __enter__(self)

    Далее выполняются инструкции внутри тела инструкции with. Если при выполнении возникло исключение, то управление передается методу __exit__(). Метод имеет следующий формат:

  __exit__(self, <Тип исключения>, <Значение>, <Объект traceback>)

    Значения, доступные через последние три параметра, полностью эквивалентны значениям, возвращаемым функцией exc_infо() из модуля sys. Если исключение обработано, метод должен вернуть значение True, в противном случае - False. Если метод возвращает False, то исключение передается вышестоящему обработчику.

    Если при выполнении инструкций, расположенных внутри тела инструкции with, исключение не возникло, то управление все равно передается методу __exit__(). В этом случае последние три параметра будут содержать значение None.

    Рассмотрим последовательность выполнения протокола на примере:

class MyClass:
    def __enter__ (self):
        print("Вызван метод __enter__()")
        return self
    def	__exit__(self, Type, Value, Trace):
        print("Вызван метод __exit__()")
        if Type is None:  # Если исключение не возникло
            print("Исключение не возникло")
        else:             # Если возникло исключение
            print("Value =", Value)
            return False  # False - исключение не обработано
                          # True  - исключение обработано

print("Последовательность при отсутствии исключения:")
with MyClass():
    print("Блок внутри with")
print ( "\nПоследовательность при наличии исключения:")
with MyClass() as obj:
    print("Блок внутри with")
    raise TypeError("Исключение TypeError")
Архив с файлом можно взять здесь.

    Результат работы приложения:

Последовательность при отсутствии исключения:
Вызван метод __enter__()
Блок внутри with
Вызван метод __exit__()
Исключение не возникло

Последовательность при наличии исключения:
Вызван метод __enter__()
Блок внутри with
Вызван метод __exit__()
Value = Исключение TypeError
Traceback (most recent call last):
  File "C:/Python34/Files_Site/pr150_1.py", line 20, in 
    raise TypeError("Исключение TypeError")
TypeError: Исключение TypeError

    Некоторые встроенные объекты поддерживают протокол по умолчанию - например, файлы. Если в инструкции with указана функция open (), то после выполнения инструкций внутри блока файл автоматически будет закрыт. Пример использования инструкции with:

with open("test.txt", "a", encoding="utf-8") as f:
    f.write("Строка\n") # Записываем строку в конец файла

    В этом примере файл test.txt открывается на дозапись в конец файла. После выполнения функции open () переменной f будет присвоена ссылка на объект файла. С помощью этой переменной мы можем работать с файлом внутри тела инструкции with. После выхода из блока вне зависимости от наличия исключения файл будет закрыт.

    На следующем шаге мы рассмотрим классы встроенных исключений.




Предыдущий шаг Содержание Следующий шаг