Извлечение типа, файла и строки исключений в Python

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для того чтобы получить тип, файл и номер строки исключения, следует использовать модуль traceback и функцию sys.exc_info():

Python
Скопировать код
import traceback
import sys

try:
    # Здесь может возникнуть ошибка... 🐉
    raise ValueError('Произошла ошибка значения')
except Exception:
    # Время разобраться... 🕵️‍♂️
    exc_type, _, exc_tb = sys.exc_info()
    fname = traceback.extract_tb(exc_tb)[-1].filename
    line = traceback.extract_tb(exc_tb)[-1].lineno
    print(f"Тип исключения: {exc_type.__name__}")
    print(f"Имя файла: {fname}")
    print(f"Номер строки: {line}")

В блоке except мы извлекаем тип исключения (exc_type.__name__), имя файла (fname) и номер строки (line).

Кинга Идем в IT: пошаговый план для смены профессии

Глубокое погружение: Столкновение с неизвестным

Работа с сложными структурами кода

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

Python
Скопировать код
import traceback

# Функция, сгенерирующая ошибку 🔥
def cause_error():
    try:
        {}['non_existent_key'] # Это вызовет KeyError
    except KeyError as e:
        raise ValueError('Ошибка KeyError преобразована во ValueError.') from e

try:
    cause_error()
except ValueError as e:
    tb = e.__traceback__
    # Обходим трассировки
    while tb:
        print(f"Имя файла: {tb.tb_frame.f_code.co_filename}, строка {tb.tb_lineno}, метод: {tb.tb_frame.f_code.co_name}")
        tb = tb.tb_next

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

Оптимизация процесса

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

Python
Скопировать код
import logging

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.ERROR) # Не шутки!

try:
    # Код, который может вызвать падение программы
except Exception as error:
    logger.exception('Поймали баг!') # Записываем трассировку исключения

Таким образом мы получаем полную трассировку стека без дополнительных усилий на форматирование.

Улучшение форматирования трассировки

Функции traceback.format_exc() и traceback.format_exception() – прекрасные инструменты, если требуется контролировать форматирование трассировок.

Python
Скопировать код
import traceback
import sys

try:
    # Код, подверженный ошибкам 🌋
except Exception:
    formatted_traceback = ''.join(traceback.format_exception(*sys.exc_info()))
    # Хранить преобразованные трассировки для анализа 👓

Вы можете адаптировать форматирование под стандарты вашего проекта или свои эстетические предпочтения.

Визуализация

Markdown
Скопировать код
Детективная работа (🕵️: раскрываем тайны исключений 🕵️)

Вот шаблон бинго, который всегда будет под рукой 🔍:

Markdown
Скопировать код
| Улика | Инструмент (возможности Python) |
|-------|--------------------------------------|
| Тип исключения | type(exc) |
| Место событий (файл, конечно же) | exc.__traceback__.tb_frame.f_code.co_filename |
| Номер строки с ошибкой | exc.__traceback__.tb_lineno |

Следуя этому пути, вы сможете разгадать пазл ошибки.

Markdown
Скопировать код
Алгоритм: 🕵️→🔎(Тип) →📁(Файл) →🚩(Строка)

Осторожно, ловушки!

Распространённые ошибки и способы их решения

Нужно быть внимательными при обработке исключений:

  • Игнорирование истинных причин исключений может скрывать реальную причину ошибки. Применяйте атрибут __cause__ у исключений, чтобы все стало на свои места.
  • Циклические ссылки могут вызвать бесконечные циклы. Используйте команду del для удаления таких ссылок и предотвращения утечек памяти.
  • Подавление исключений усложняет отладку. Документируйте исключения, даже если они преднамеренно игнорируются.

Зернышки мудрости

Профессиональные рекомендации по обработке исключений:

  • Функция os.path.basename() позволит вам видеть только имя файла, пропуская полный путь:

    Python
    Скопировать код
    fname = os.path.basename(exc_tb.tb_frame.f_code.co_filename)
  • Перехватчики исключений с помощью sys.excepthook помогают вытащить необработанные ошибки на свет божий.
  • Менеджеры контекста с использованием contextlib облегчают работу с исключениями.

Полезные материалы

  1. inspect — Inspect live objects — Python 3.12.1 documentation — Продвинутое руководство по инспекции объектов в реальном времени в Python.
  2. traceback — Print or retrieve a stack traceback — Python 3.12.1 documentation — Подробная информация о модуле traceback.
  3. sys — Системно-специфические параметры и функции — Python 3.12.1 documentation — Справочные данные о функции sys.exc_info() для работы с исключениями.
  4. exception – Как залогировать ошибку Python с отладочной информацией? – Stack Overflow на русском — Проверенные сообществом методы логирования исключений в Python.
  5. Книга рецептов логирования — Python 3.12.1 documentation — Глубокое погружение в настройку логирования в Python.
  6. PEP 3134 – Цепочки исключений и встроенные трассировки | peps.python.org — Информация о цепочках исключений и встроенных трассировках.
  7. Python Исключения: Введение – Real Python — Основной курс по обработке исключений для реальных программистов.