Traceback — это отчет интерпретатора Python о цепочке вызовов функций, которая привела к необработанному исключению. Он печатается в консоль, когда программа падает, и содержит путь по стеку вызовов плюс тип и текст ошибки в последней строке. В статье разберем, как читать traceback, где искать свою строку кода и чем он отличается от exception и error.
Содержание
Traceback, exception и error — в чем разница
Эти три слова часто путают, хотя это разные вещи.
Exception (исключение) — это объект в памяти, который Python создает при сбое: ValueError, KeyError, TypeError и другие. Его можно поймать блоком try/except, у него есть тип и сообщение.
Error (ошибка) — в Python это, как правило, синоним подкласса Exception, который обозначает именно программную ошибку (ValueError, TypeError), а не любое исключение вообще (есть исключения, которые ошибкой не являются, например StopIteration). В разговорной речи error часто используют шире — как «что-то пошло не так».
Traceback (трассировка) — это не сам сбой, а отчет о пути к нему: список кадров стека от точки входа в программу до строки, где исключение возникло.
Цепочка происходящего: raise ValueError("...") создает объект-исключение -> он поднимается вверх по стеку вызовов -> если ни один except его не поймал, интерпретатор печатает traceback и в последней строке — тип и текст исключения.
Из чего состоит traceback
Возьмем типичный вывод:
Traceback (most recent call last):
File "shop.py", line 13, in <module>
print(compute_total(items))
File "shop.py", line 8, in compute_total
total += parse_price(item)
File "shop.py", line 2, in parse_price
return float(text)
ValueError: could not convert string to float: 'abc'
Здесь три части:
- Последняя строка — тип исключения и его сообщение (
ValueError: could not convert...). Это самое важное: что именно сломалось. - Блоки кадров (
File ... line ... in ...) — каждый кадр это файл, номер строки и имя функции, где выполнение было в момент сбоя. Под каждым кадром — сама строка кода. - Заголовок
Traceback (most recent call last)— предупреждение, что порядок кадров идет от самого раннего вызова к самому позднему (то есть к месту сбоя).
Как читать traceback: алгоритм
- Начните с последней строки — тип и текст исключения. Это диагноз.
- Поднимитесь на один кадр вверх (блок прямо над последней строкой) — это место, где исключение фактически возникло.
- Проверьте путь файла в этом кадре. Если это
site-packages,lib/python3.xили другой не ваш путь — это библиотечный код, и настоящая причина обычно в вызове чуть выше. - Продолжайте подниматься по кадрам, пока не найдете первый файл из вашего проекта — это и есть строка, которую нужно чинить.
- Если кадров несколько в вашем же коде, кадр ближе к концу списка обычно точнее указывает на симптом, а кадр выше — на причину (откуда пришли неверные данные).
Разберем на примере выше. Последняя строка говорит: ValueError: could not convert string to float: 'abc'. Кадр над ней — parse_price, строка 2, return float(text): здесь float() не смог разобрать строку. Кадр выше — compute_total, строка 8: здесь parse_price вызвали с плохим значением. Кадр <module>, строка 13 — точка входа. Если весь код ваш, чинить нужно либо валидацию в parse_price, либо фильтрацию входных данных в compute_total.
Полный пример с воспроизводимой ошибкой
Код в файле shop.py:
def parse_price(text):
return float(text)
def compute_total(items):
total = 0
for item in items:
total += parse_price(item)
return total
items = ["10.5", "20", "abc"]
print(compute_total(items))
Запуск python shop.py даст ровно тот traceback, что разобран выше:
Traceback (most recent call last):
File "shop.py", line 13, in <module>
print(compute_total(items))
File "shop.py", line 8, in compute_total
total += parse_price(item)
File "shop.py", line 2, in parse_price
return float(text)
ValueError: could not convert string to float: 'abc'
Исправление — проверять значение до преобразования и пропускать некорректные строки:
def parse_price(text):
try:
return float(text)
except ValueError:
return None
def compute_total(items):
total = 0
for item in items:
price = parse_price(item)
if price is not None:
total += price
return total
items = ["10.5", "20", "abc"]
print(compute_total(items))
Вывод после исправления:
30.5
Значение 'abc' теперь просто пропускается, а не роняет программу.
Модуль traceback: print_exc и format_exc
Если исключение поймано в try/except, Python не печатает traceback сам — его нужно вывести вручную. Для этого есть встроенный модуль traceback.
traceback.print_exc() печатает трассировку текущего перехваченного исключения в поток ошибок (stderr), не прерывая программу:
import traceback
try:
compute_total(["10.5", "abc"])
except ValueError:
traceback.print_exc()
print("Программа продолжает работать")
Вывод:
Traceback (most recent call last):
File "shop.py", line 20, in <module>
compute_total(["10.5", "abc"])
File "shop.py", line 8, in compute_total
total += parse_price(item)
File "shop.py", line 2, in parse_price
return float(text)
ValueError: could not convert string to float: 'abc'
Программа продолжает работать
traceback.format_exc() делает то же самое, но возвращает текст строкой, а не печатает — это удобно для логирования:
import logging
import traceback
try:
compute_total(["10.5", "abc"])
except ValueError:
logging.error("Не удалось посчитать сумму:\n%s", traceback.format_exc())
Так полный traceback попадет в файл лога вместе с остальными сообщениями, а не потеряется в консоли.
Когда traceback длиннее: цепочки исключений
Иногда обработка одного исключения вызывает второе. Тогда Python печатает обе трассировки подряд, разделяя их строкой During handling of the above exception, another exception occurred:. Первая напечатанная трассировка — исходная причина, вторая — то, что случилось при попытке ее обработать. Читать нужно обе, начиная с верхней (исходной) части.
Выводы
- Traceback — это отчет о пути вызовов до сбоя, а не сам сбой; exception — объект ошибки, error — обычно подкласс Exception для программных ошибок.
- Начинайте чтение с последней строки (тип и текст ошибки), затем поднимайтесь по кадрам вверх.
- Первый кадр с путем внутри вашего проекта — это строка, которую нужно чинить; библиотечные кадры обычно указывают на симптом, а не причину.
traceback.print_exc()иtraceback.format_exc()нужны, когда исключение уже поймано вexcept, а трассировку все равно нужно увидеть или записать в лог.- Строка
During handling of the above exception...означает, что перед вами две связанные трассировки, а не одна.
Где применяется / связь с практикой
Освойте тему на практике
Чтение traceback — базовый навык отладки, без которого сложно разбираться даже в чужом коде: логах веб-сервера, тестах, продакшен-ошибках. Если вы только начинаете работать с Python и хотите закрыть такие пробелы системно, а не по отдельным статьям, посмотрите курс Python с нуля — там разбор ошибок и отладка идут отдельным модулем на практике. Проверить формат подачи можно и без обязательств — на открытых уроках Otus.
FAQ
Почему в traceback фигурирует stdin вместо имени файла?
Так бывает при работе в интерактивном режиме REPL: код выполняется не из файла, а построчно из ввода, поэтому вместо пути указывается stdin, а строки кода под кадром не показываются.
Можно ли получить traceback в виде переменной, а не печатать его?
Да, для этого traceback.format_exc() возвращает готовый текст строкой, а traceback.extract_tb() — структурированный список кадров, если нужно обрабатывать их программно.
Чем StopIteration отличается от типичных error-исключений вроде ValueError?
StopIteration — служебный сигнал для итераторов (что элементы закончились), а не признак программной ошибки; в большинстве кода его ловит сам механизм for, и разработчик с ним напрямую не работает.



