Перейти к содержимому
Editor

Ошибки в Python: как читать traceback и исправлять частые баги

Начальный20 min6 упр.75 XP

Этот урок переведён с английского оригинала.Read in EnglishLeer en españolСообщить об ошибке в переводе

0/6 упр.

Увидев красное сообщение об ошибке, новичок первым делом паникует. Экран заполняется пугающим текстом, и кажется, что вы что-то серьёзно сломали. Но правда в том, что лучшего друга, чем сообщение об ошибке, у вас нет. Оно точно говорит, что пошло не так и где.

Профессиональные программисты видят ошибки каждый день. Эксперт отличается от новичка не тем, что не допускает ошибок, а тем, что умеет их читать. Как только вы научитесь читать сообщения об ошибках Python, отладка из пугающего занятия превратится в почти автоматическое.

В этом уроке вы научитесь читать трассировку (traceback) в Python, разберётесь в шести самых частых типах ошибок и соберёте в голове набор приёмов, которые помогают быстро исправлять баги.

Как читать трассировку (traceback) в Python

Когда Python натыкается на ошибку, он выводит трассировку: отчёт о том, что произошло. Большинство людей читают трассировку сверху вниз, а нужно наоборот. Всегда начинайте с последней строки.

Код, который выводит трассировку
def greet(name):
message = 'Hello, ' + name
return message
result = greet(42)
Вывод
Traceback (most recent call last):
  File "<exec>", line 5, in <module>
  File "<exec>", line 2, in greet
TypeError: can only concatenate str (not "int") to str

Если запустить этот код, Python покажет трассировку. Вот как её читать, начиная снизу:


SyntaxError: Python не понимает ваш код

SyntaxError означает, что Python даже не может начать выполнять ваш код, потому что у него неправильная структура. Это похоже на грамматическую ошибку в обычной речи: предложение теряет смысл. Python находит такие ошибки ещё до того, как выполнит хотя бы одну строку.

Частые причины SyntaxError
# Missing colon after if
try:
exec('if True\n print("hello")')
except SyntaxError as e:
print(f'SyntaxError: {e}')
# These are the most common causes:
print('Common SyntaxError causes:')
print('1. Missing colon after if/else/for/while/def')
print('2. Mismatched parentheses or quotes')
print('3. Using = instead of == in conditions')
print('4. Incorrect indentation')
Вывод
SyntaxError: expected ':' (<string>, line 1)
Common SyntaxError causes:
1. Missing colon after if/else/for/while/def
2. Mismatched parentheses or quotes
3. Using = instead of == in conditions
4. Incorrect indentation

Хорошая новость: SyntaxError обычно исправить проще всего. Python часто указывает прямо на проблему маленькой стрелкой (^) в том месте, где он запутался.

Ошибка: нет двоеточия
if temperature > 30
    print('Hot!')
Исправлено: двоеточие добавлено
if temperature > 30:
    print('Hot!')

NameError: Python не может найти имя

NameError означает, что вы использовали имя переменной или функции, которое Python не знает. Обычно причина в опечатке, в забытом определении переменной или в том, что переменную использовали до присваивания ей значения.

Частые примеры NameError
# Typo in variable name
username = 'Alice'
try:
print(usernme) # Oops - misspelled!
except NameError as e:
print(f'NameError: {e}')
# Using a variable before defining it
try:
print(score)
score = 100
except NameError as e:
print(f'NameError: {e}')
Вывод
NameError: name 'usernme' is not defined
NameError: name 'score' is not defined
Ошибка: опечатка в имени переменной
total_price = 49.99
print(total_prce)  # typo!
Исправлено: правильное написание
total_price = 49.99
print(total_price)

TypeError: неподходящий тип для операции

TypeError означает, что вы попытались сделать что-то с данными неподходящего типа. Например, сложить строку и число или вызвать то, что не является функцией. Python понимает, чего вы хотите, но типы не совпадают.

Частые примеры TypeError
# Can't add string and integer
try:
result = 'Age: ' + 25
except TypeError as e:
print(f'TypeError: {e}')
# Can't multiply string by string
try:
result = 'hello' * 'world'
except TypeError as e:
print(f'TypeError: {e}')
# Wrong number of arguments
def add(a, b):
return a + b
try:
add(1, 2, 3)
except TypeError as e:
print(f'TypeError: {e}')
Вывод
TypeError: can only concatenate str (not "int") to str
TypeError: can't multiply sequence by non-int of type 'str'
TypeError: add() takes 2 positional arguments but 3 were given

TypeError часто появляется при работе с вводом пользователя (он всегда приходит строкой) или когда функция неожиданно возвращает None.

Ошибка: строка и int вперемешку
age = 25
print('You are ' + age + ' years old')
Исправлено: f-строка или str()
age = 25
print(f'You are {age} years old')

IndexError и KeyError: обращение к тому, чего нет

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

Примеры IndexError и KeyError
# IndexError - list index out of range
fruits = ['apple', 'banana', 'cherry']
try:
print(fruits[5]) # Only indices 0, 1, 2 exist!
except IndexError as e:
print(f'IndexError: {e}')
print(f'List length: {len(fruits)}')
print(f'Valid indices: 0 to {len(fruits) - 1}')
# KeyError - dictionary key doesn't exist
user = {'name': 'Alice', 'age': 25}
try:
print(user['email']) # This key doesn't exist!
except KeyError as e:
print(f'KeyError: {e}')
Вывод
IndexError: list index out of range
List length: 3
Valid indices: 0 to 2
KeyError: 'email'

В словарях KeyError можно избежать с помощью метода .get(): вместо ошибки он возвращает значение по умолчанию.

Завершается с KeyError
user = {'name': 'Alice'}
email = user['email']  # KeyError!
Безопасно с .get()
user = {'name': 'Alice'}
email = user.get('email', 'Not provided')
print(email)  # Not provided

ValueError: тип верный, значение нет

ValueError означает, что тип правильный, но само значение не подходит для операции. Классический пример: попытка превратить в целое число строку, в которой записано не число.

Частые примеры ValueError
# Can't convert "hello" to an integer
try:
number = int('hello')
except ValueError as e:
print(f'ValueError: {e}')
# Can't convert a decimal string with int()
try:
number = int('3.14')
except ValueError as e:
print(f'ValueError: {e}')
# This works - go through float first
number = int(float('3.14'))
print(f'Converted: {number}')
Вывод
ValueError: invalid literal for int() with base 10: 'hello'
ValueError: invalid literal for int() with base 10: '3.14'
Converted: 3

ValueError часто встречается при обработке ввода пользователя. Пользователь может ввести «двадцать» вместо «20» или оставить поле пустым. Всегда проверяйте ввод перед преобразованием.

Обработка ValueError с помощью try/except
# Safe conversion pattern
user_input = 'abc'
try:
age = int(user_input)
print(f'Your age is {age}')
except ValueError:
print(f'\"{user_input}\" is not a valid number')
Вывод
"abc" is not a valid number

Полезные советы по отладке

Вот краткая шпаргалка по отладке кода на Python. Эти приёмы работают для ошибок любого типа.

Вот краткая справка по ошибкам, которые будут встречаться вам чаще всего:

ОшибкаЧто означаетКак быстро исправить
SyntaxErrorНеправильная структура кодаПроверьте двоеточия, скобки, кавычки
NameErrorПеременная или функция не найденаПроверьте написание, определяйте до использования
TypeErrorНеподходящий тип данныхПреобразуйте типы или проверьте аргументы функции
IndexErrorИндекс списка вне диапазонаПроверьте длину списка, помните, что индексы начинаются с 0
KeyErrorКлюч словаря не найденИспользуйте .get() или проверьте, что ключ есть
ValueErrorТип верный, значение нетПроверяйте данные перед преобразованием

Упражнения

Пора потренировать навыки отладки! В большинстве упражнений вам дан неисправный код. Прочитайте сообщение об ошибке, найдите баг и исправьте его.

Упражнение 1: исправьте SyntaxError
Исправьте ошибку

В этом коде есть SyntaxError. Найдите и исправьте ошибку, чтобы программа вывела:

Python is fun!
Let's learn more.
message = 'Python is fun!'
print(message
print('Let\'s learn more.')
Упражнение 2: исправьте NameError
Исправьте ошибку

В этом коде есть NameError. Найдите опечатку и исправьте её, чтобы программа вывела:

Hello, Alice! You have 3 new messages.
user_name = 'Alice'
message_count = 3
print(f'Hello, {user_name}! You have {mesage_count} new messages.')
Упражнение 3: исправьте TypeError
Исправьте ошибку

В этом коде есть TypeError. Исправьте его, чтобы программа вывела:

Your total is $37.5
price = 12.5
quantity = '3'
total = price * quantity
print(f'Your total is ${total}')
Упражнение 4: исправьте IndexError
Исправьте ошибку

Этот код пытается вывести последний цвет, но завершается с IndexError. Исправьте его, чтобы программа вывела:

Last color: green
colors = ['red', 'blue', 'green']
last_index = len(colors)
print(f'Last color: {colors[last_index]}')
Упражнение 5: исправьте ValueError
Исправьте ошибку

Этот код завершается с ошибкой, когда пытается преобразовать строку с ценой в целое число. Исправьте его, чтобы программа вывела:

Price in cents: 999

Цена составляет "9.99" доллара, и мы хотим перевести её в центы (умножить на 100 и округлить до целого числа).

price_str = '9.99'
price_cents = int(price_str) * 100
print(f'Price in cents: {price_cents}')
Упражнение 6: исправьте все ошибки
Исправьте ошибку

В этом коде ТРИ ошибки (по одной в каждом разделе, разделы отмечены комментариями Bug 1, Bug 2 и Bug 3). Исправьте их все, чтобы вывод был таким:

Student: Alice
Grade: 85
Passed: True
# Bug 1: Something wrong with the variable name
student_name = 'Alice'
print(f'Student: {student_Name}')
# Bug 2: Something wrong with the type
grade = '85'
print(f'Grade: {grade + 0}')
# Bug 3: Something wrong with the comparison
passed = grade >= 60
print(f'Passed: {passed}')

Итоги: сообщения об ошибках в Python

Вот краткая справка по самым частым ошибкам в Python:

ОшибкаЗначениеЧто проверить первым делом
SyntaxErrorНеправильная структура кодаПропущенные двоеточия, скобки, кавычки
NameErrorНеизвестная переменнаяНаписание имени, порядок определения
TypeErrorНеподходящий типПроверьте типы с помощью type()
IndexErrorНеверный индекс спискаДлина списка, индексы с 0
KeyErrorНеверный ключ словаряИспользуйте .get() со значением по умолчанию
ValueErrorНеподходящее значениеПроверяйте перед преобразованием

Золотые правила отладки:

  • Всегда начинайте с последней строки трассировки
  • Проверяйте номер строки, который указывает Python (и строку перед ней)
  • Используйте print(type(x), x), чтобы проверить подозрительные переменные
  • Сообщения об ошибках вам помогают, а не мешают: они точно говорят, что пошло не так
  • Что дальше?

    Теперь, когда вы умеете читать сообщения об ошибках, можно уверенно браться за более сложные темы Python. Переходите к уроку [Списки в Python](/python/python-lists) и познакомьтесь с одной из самых мощных и универсальных структур данных в Python.

    Похожие уроки

    Урок был полезен?