Менеджер контекста в 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')
Если нет ошибок, то процесс следующий
- The with statement stores the __exit__ method of the File class.
- It calls the __enter__ method of the File class.
- The __enter__ method opens the file and returns it.
- The opened file handle is passed to f.
- We write to the file using .write().
- The with statement calls the stored __exit__ method.
- 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.write … with 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 |
РЕКЛАМА от Яндекса. Может быть недоступна в вашем регионе
Конец рекламы от Яндекса. Если в блоке пусто считайте это рекламой моей телеги