1.1 Возникновение ошибки
Ошибки (и исключения) являются неотъемлемой частью программирования. Они возникают, когда программа сталкивается с непредвиденными ситуациями, которые она не может обработать. В Python существует система обработки исключений, которая позволяет перехватывать и обрабатывать ошибки, предотвращая завершение программы.
Исключения чаще всего возникают в следующих ситуациях:
Синтаксические ошибки:
Эти ошибки обнаруживаются на этапе компиляции кода и связаны с неправильной грамматикой языка Python. Например, пропущенные двоеточия или неверные ключевые слова.
if True:
print("Hello")
Ошибки времени выполнения (Runtime Errors)
:
Эти ошибки возникают во время выполнения программы и могут быть вызваны различными причинами, такими как деление на ноль, доступ к несуществующему индексу списка, неправильное использование типов данных и т.д.
print(1 / 0) # ZeroDivisionError
Логические ошибки:
Эти ошибки возникают, когда программа работает без сбоев, но выдает неправильный результат из-за ошибки в логике программы. Логические ошибки не вызывают исключений, и их сложнее отладить.
Логические ошибки обычно называют багами — это как бы некоторая недоработка функционала программы. Ошибки же времени выполнения называют исключениями. Для каждой такой ошибки Python создает специальный объект (исключение) и «вбрасывает» его в программу...
1.2 Путь исключений
Когда в Python возникает исключение, оно поднимается по стеку вызовов, пока не будет обработано. Стек вызовов представляет собой последовательность вызовов функций, которые привели к возникновению исключения.
Механизм подъема исключений
- Возникновение исключения: Когда происходит ошибка, Python создает объект исключения.
- Поиск обработчика исключения: Интерпретатор Python начинает поиск обработчика исключения в текущем блоке кода. Если обработчик не найден, он переходит к следующему блоку кода, который вызвал текущую функцию.
- Подъем исключения по стеку: Этот процесс повторяется, пока не будет найден обработчик или стек вызовов не будет исчерпан.
- Завершение программы: Если обработчик не найден, программа завершает свою работу и выводит сообщение об ошибке.
Пример:
def func_a():
func_b()
def func_b():
func_c()
def func_c():
print(1 / 0) # Здесь возникает исключение ZeroDivisionError
func_a()
В этом примере исключение ZeroDivisionError
возникает в функции func_c
, затем поднимается по стеку вызовов через func_b
и func_a
. Если нигде не будет найден обработчик, программа завершится с ошибкой.
1.3 Чтение лога
Когда программа завершается из-за необработанного исключения, Python выводит трассировку стека (traceback), которая помогает разработчикам понять, что пошло не так. Трассировка стека содержит информацию о последовательности вызовов функций, которые привели к возникновению исключения, и может быть проанализирована для отладки программы.
Пример трассировки стека
Traceback (most recent call last):
File "example.py", line 10, in
func_a() File "example.py", line 2, in func_a func_b() File "example.py", line 5, in func_b func_c() File "example.py", line 8, in func_c print(1 / 0) ZeroDivisionError: division by zero
Анализ трассировки стека
- Тип исключения и сообщение: В конце трассировки указывается тип исключения и сообщение. В приведенном примере это
ZeroDivisionError: division by zero
. - Последовательность вызовов: Трассировка стека показывает последовательность вызовов функций. В нашем примере ошибка произошла в строке
print(1 / 0)
в функцииfunc_c
, которая была вызвана изfunc_b
, которая в свою очередь была вызвана изfunc_a
. - Файлы и строки кода: В каждой строке трассировки указывается файл и номер строки, где произошел вызов. Это помогает быстро найти и исправить ошибку в коде.
Практическое использование трассировки стека
Трассировка стека является важным инструментом для отладки и анализа программ. Она помогает разработчикам понять причину возникновения ошибки и найти место в коде, где она произошла. Вот несколько советов по использованию трассировки стека:
- Чтение снизу вверх: Начинайте анализ с самого нижнего вызова в трассировке, поскольку это место, где произошло исключение.
- Проверка всех вызовов: Изучите все вызовы в трассировке, чтобы понять путь, по которому передавалось исключение.
- Исправление кода: Используйте информацию из трассировки для исправления кода и предотвращения аналогичных ошибок в будущем.
Более подробно об исключениях вы узнаете в следующих лекциях.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ