Найти в Дзене
Машинное обучение

Хорошо ли вы знаете исключения в Python?

​​​​

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

Unexpected exception:

Что-то постоянно ломается, но молча.

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

try:
raise KeyError
except Exception as e:
print(f"Unexpected exception: {e}")

Если выполнить этот пример, то и получится

Unexpected exception:

Дело в том, что есть четыре способа вывести сообщение пойманного исключения:

🐟 print(e)
🐟 print(str(e))
🐟 print(e.message)
🐟 print(repr(e))

Первые два варианта не очень информативны. Например, если попытаться обратиться к несуществующему ключу словаря (ошибка топ 1 в Python), то эти варианты выведут только название ключа.

my_dict = {}
try:
b = my_dict["bad"]
except Exception as e:
print(f"Unexpected exception: {e}")
Unexpected exception: 'bad'

Это потому, что str(e) и e выводят сообщение исключения, но не его тип. Чаще всего этого достаточно, но исключения для того и нужны, чтобы сообщать о ситуациях, которых мы не ожидаем.

Иногда пишут print(e.message). Здесь проблемы целых две: во-первых, мы по-прежнему получаем только сообщение. А во-вторых, атрибут message определен не у всех исключений. Если не снабдить наш print условием, то мы получим только новую ошибку:

AttributeError: 'KeyError' object has no attribute 'message'

А вот магический метод repr, который и нужен для того, чтобы давать максимально точное описание, все сделает отлично. Сравним:

try:
raise KeyError
except Exception as e:
print(f"Unexpected exception: {repr(e)}")
Unexpected exception: KeyError()

А в примере со словарем получилось бы

Unexpected exception: KeyError('bad')

что более явно, чем все три варианта выше 🐠

#исключения

Python RU

#python #pythons #pythonsofig #pets #petstagram #herps #royalpython #snakebreeder #nature