Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как искать ошибку в коде
Поиск и исправление ошибок (debugging) — это один из самых важных навыков разработчика. Я использую систематический подход, который помогает найти проблему быстро и надёжно.
1. Понимание ошибки
Первый шаг — понять, что именно пошло не так:
# Пример ошибки
Traceback (most recent call last):
File "app.py", line 42, in process_user
age = int(user['age'])
ValueError: invalid literal for int() with base 10: 'unknown'
Эта ошибка говорит мне:
- Где произошла ошибка (строка 42)
- Что произошло (ValueError)
- Почему (невалидное значение для int())
2. Воспроизведение ошибки
Нужно понять, при каких условиях ошибка возникает:
# Тестовые данные для воспроизведения
test_cases = [
{'name': 'John', 'age': '25'}, # OK
{'name': 'Jane', 'age': 'unknown'}, # ERROR
{'name': 'Bob', 'age': ''}, # ERROR
{'name': 'Alice'}, # KeyError
]
for user in test_cases:
try:
age = int(user['age'])
print(f"OK: {user['name']} - {age}")
except (ValueError, KeyError) as e:
print(f"ERROR: {user} - {e}")
3. Использование логирования
Добавляю логи в ключевые места кода:
import logging
logger = logging.getLogger(__name__)
def process_user(user: dict):
logger.debug(f"Processing user: {user}")
try:
age = int(user['age'])
logger.info(f"Age converted: {age}")
except ValueError as e:
logger.error(f"Cannot convert age: {user['age']}", exc_info=True)
raise
return {'name': user['name'], 'age': age}
Логи помогают отследить путь выполнения и найти момент, когда данные становятся некорректными.
4. Debugger (pdb)
Для сложных случаев использую встроенный debugger Python:
import pdb
def process_user(user: dict):
name = user.get('name')
age_str = user.get('age')
pdb.set_trace() # Точка останова
age = int(age_str)
return {'name': name, 'age': age}
В момент останова можно:
- Просмотреть переменные:
p user - Выполнить код:
n(next),s(step) - Посмотреть стек:
w(where) - Вывести значение:
pp var_name
5. Юнит-тесты
Написание тестов помогает изолировать проблему:
import pytest
def convert_age(age_str: str) -> int:
if not age_str or not age_str.isdigit():
raise ValueError(f"Invalid age: {age_str}")
return int(age_str)
def test_convert_age():
assert convert_age('25') == 25
with pytest.raises(ValueError):
convert_age('unknown')
with pytest.raises(ValueError):
convert_age('')
Тесты показывают нормальное и аномальное поведение.
6. Логическое рассуждение
Лучший инструмент — это критическое мышление:
# Вопросы, которые я себе задаю:
# 1. Это может быть None?
age = user.get('age')
if age is None:
logger.warning("Age is None")
age = 0
# 2. Это может быть пустой строкой?
if age == '':
logger.warning("Age is empty string")
age = 0
# 3. Это может быть неправильного типа?
if not isinstance(age, (int, str)):
raise TypeError(f"Age must be int or str, got {type(age)}")
# 4. Граничные случаи?
if age < 0 or age > 150:
raise ValueError(f"Age out of range: {age}")
7. Использование IDE
Современные IDE помогают найти ошибки:
# IDE подчеркивает:
# 1. Type errors (если переменная неправильного типа)
user: dict = get_user()
age = user.get('age') # IDE знает, что это может быть None
# 2. Unused variables
temp_var = 5 # Если не используется, IDE покажет warning
# 3. Undefined names
print(undefined_variable) # IDE предупредит перед запуском
8. Code Review
Часто ошибка видна при внимательном чтении:
# Ошибка: используется = вместо ==
if x = 5: # SyntaxError
pass
# Ошибка: неправильный порядок параметров
def divide(a, b):
return a / b
result = divide(10, 2) # OK: 5
result = divide(2, 10) # ОШИБКА: 0.2 вместо 5
9. Проверка зависимостей
Старые версии библиотек могут быть причиной:
# Обновить зависимости
pip list --outdated
pip install --upgrade pip
pip install -r requirements.txt --upgrade
# Проверить версии
python -c "import requests; print(requests.__version__)"
10. Дев-окружение vs Продакшен
Ошибки часто появляются только в продакшене:
# Проверить конфигурацию окружения
import os
print(f"DEBUG: {os.getenv('DEBUG')}")
print(f"DATABASE_URL: {os.getenv('DATABASE_URL')}")
# Если вижу ошибку в продакшене:
# 1. Проверю env переменные
# 2. Проверю версии пакетов
# 3. Посмотрю логи сервера
# 4. Репродуцирую локально с тем же конфигом
Мой алгоритм debugging
1. Изучаю ошибку (stacktrace, сообщение)
2. Воспроизвожу её локально
3. Добавляю логирование вокруг проблемного места
4. Пишу юнит-тест, который ловит ошибку
5. Читаю код логически
6. Использую debugger для inspect переменных
7. Исправляю ошибку
8. Убеждаюсь, что тест проходит
9. Проверяю, не привёл ли я к другим ошибкам
Заключение
Дебаггинг — это не магия, а системный процесс. Чем больше информации ты соберёшь, тем быстрее найдёшь проблему. Самое важное — не паниковать, а методично исследовать код.