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

Содержание
Введение
Пример написания
as
Своя версия open
Обработка ошибок
Похожие статьи

Введение

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

Входное действие задаётся в методе __enter__(), выходное в методе __exit__()

__exit__() должен принимать три позиционных аргумента которые содержат информацию об исключениях:

тип исключения, содержимое и трейсбэк.

Пример с их применением вы можете изучить здесь

Официальная документация:

context-managers , with

Возможно самый популярный пример применения - with open() для открытия файлов .

РЕКЛАМА от Яндекса. Может быть недоступна в вашем регионе

Конец рекламы от Яндекса. Если в блоке пусто считайте это рекламой моей телеги

Пример

class Example: def __enter__(self): print("enter") def __exit__(self, exc_type, exc_val, exc_tb): print("exit") with Example(): print("Yay Python!")

enter Yay Python! exit

Более практичный пример - менеджер контекста будет временно изменять переменную окружения.

import os class set_env_var: def __init__(self, var_name, new_value): self.var_name = var_name self.new_value = new_value def __enter__(self): self.original_value = os.environ.get(self.var_name) os.environ[self.var_name] = self.new_value def __exit__(self, exc_type, exc_val, exc_tb): if self.original_value is None: del os.environ[self.var_name] else: os.environ[self.var_name] = self.original_value print("USERNAME env var is", os.environ["USERNAME"]) with set_env_var("USERNAME", "DEVHOPS-RU"): print("USERNAME env var is", os.environ["USERNAME"]) print("USERNAME env var is", os.environ["USERNAME"])

USERNAME env var is ANDREI USERNAME env var is DEVHOPS-RU USERNAME env var is ANDREI

as

С помощью as можно задать переменную которая будет указывать на возвращаемое из __enter__() значение.

Если __enter__() ничего не возвращает, как в предыдущем примере, то в переменной будет None.

with set_env_var("USERNAME", "TESTSETUP-RU") as result: print("USERNAME env var is", os.environ["USERNAME"]) print("Result from __enter__ method:", result)

USERNAME env var is TESTSETUP-RU Result from __enter__ method: None

import time class Timer: def __enter__(self): self.start = time.perf_counter() return self def __exit__(self, exc_type, exc_val, exc_tb): self.stop = time.perf_counter() self.elapsed = self.stop - self.start t = Timer() with t: time.sleep(.5) print(t.elapsed) with Timer() as t: time.sleep(1) print(t.elapsed)

0.5005884999991395 1.0005807999987155

РЕКЛАМА от Google. Может быть недоступна в вашем регионе.

Конец рекламы от Google. Если в блоке пусто считайте это рекламой моей телеги

Своя версия open

class File(object): def __init__(self, file_name, method): self.file_obj = open(file_name, method) def __enter__(self): return self.file_obj def __exit__(self, exc_type, exc_value, exc_traceback): self.file_obj.close() with File('sites.md', 'w') as f: f.write('www.devhops.ru')

Если нет ошибок, то процесс следующий

  1. The with statement stores the __exit__ method of the File class.
  2. It calls the __enter__ method of the File class.
  3. The __enter__ method opens the file and returns it.
  4. The opened file handle is passed to f.
  5. We write to the file using .write().
  6. The with statement calls the stored __exit__ method.
  7. The __exit__ method closes the file.

Обработка ошибок

Если в примере со своей версией open вызвать вместо write() несуществующий метод появится исключение.

with File('sites.md', 'w') as f: f.undefined('www.devhops.ru')

Traceback (most recent call last): File "C:\Users\Andrei\context.py", line 11, in <module> f.undefined('www.devhops.ru') ^^^^^^^^^^^ AttributeError: '_io.TextIOWrapper' object has no attribute 'undefined'

Обработать его можно в методе __exit__()

class File(object): def __init__(self, file_name, method): self.file_obj = open(file_name, method) def __enter__(self): return self.file_obj def __exit__(self, exc_type, exc_value, exc_traceback): if exc_type is not None: print("Exception has been handled") print("Exception type is", exc_type) print("Exception value is", exc_value) print("Exception traceback is", exc_traceback) if exc_type is AttributeError: print("AttributeError") self.file_obj.close() return True with File('sites.md', 'w') as f: f.unknown('www.devhops.ru')

Exception has been handled Exception type is <class 'AttributeError'> Exception value is '_io.TextIOWrapper' object has no attribute 'undefined' Exception traceback is <traceback object at 0x0000016845C87D40> AttributeError

Записано в файл ничего не будет.

Если вы хотите чтобы метод undefined работал как write нужно задать это в __init__()

class File(object): def __init__(self, file_name, method): self.file_obj = open(file_name, method) self.file_obj.undefined = self.file_obj.writewith File('sites.md', 'w') as f: f.undefined('www.devhops.ru')

cat sites.md

www.devhops.ru

Похожие статьи
Основы Python
Type Hints
__future__
configparser
Менеджер контекста
docstring
#!: Shebang
Объекты
Итерация
os
pathlib

РЕКЛАМА от Яндекса. Может быть недоступна в вашем регионе

Конец рекламы от Яндекса. Если в блоке пусто считайте это рекламой моей телеги

Поиск по сайту

Подпишитесь на Telegram канал @aofeed чтобы следить за выходом новых статей и обновлением старых

Перейти на канал

@aofeed

Задать вопрос в Телеграм-группе

@aofeedchat

Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@urn.su если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящую по тематике.
3. Реклама на моём сайте имеет максимальный уровень цензуры. Если Вы увидели рекламный блок недопустимый для просмотра детьми школьного возраста, вызывающий шок или вводящий в заблуждение - пожалуйста свяжитесь с нами по электронной почте
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......
5. Статьи можно расшарить в соцсетях, нажав на иконку сети: