Отладка печатью
когда её достаточно и как делать правильно
Что это
Вставить print и посмотреть, что в переменной, — самый простой способ
отладки. Его принято считать несерьёзным, но для большинства задач он быстрее
отладчика и не требует ничего настраивать.
Статья — о том, как печатать так, чтобы это помогало, и когда всё-таки нужен отладчик.
Как выглядит в коде
Плохо
print(data)
print(x)
print("тут")Запустил, получил три непонятных вывода подряд и не знаешь, какой откуда.
Хорошо
print(f"[parse] items={len(items)} first={items[0] if items else None!r}")
print(f"[to_numbers] temp={it['temp']!r} type={type(it['temp']).__name__}")Три приёма, которые делают печать полезной:
Метка. [parse] сразу говорит, откуда строка. При десятке печатей это
экономит всё время.
!r вместо обычного вывода. repr показывает кавычки и невидимое.
Разница решающая:
value = " 42 "
print(f"value={value}") # value= 42
print(f"value={value!r}") # value=' 42 'Во втором случае сразу видно, что в строке пробелы, — а именно из-за них
int() и падал.
Тип, а не только значение. '4' и 4 выглядят почти одинаково, а ведут
себя по-разному. type(x).__name__ снимает вопрос.
Печать структуры
Для словарей и списков удобнее так:
import json
print(json.dumps(data, ensure_ascii=False, indent=2)[:500])ensure_ascii=False — чтобы русский текст был читаемым, а не р.
Срез [:500] — чтобы не залить терминал, если данных много.
Когда нужен отладчик
Печати хватает, пока ты знаешь, что печатать. Отладчик нужен, когда не знаешь:
| Печать | Отладчик |
|---|---|
| понятно, какие переменные смотреть | непонятно, что происходит вообще |
| один-два прохода | нужно пройти шаг за шагом |
| код запускается быстро | каждый запуск долгий |
| всё в своём коде | ошибка где-то в чужой библиотеке |
Самый дешёвый отладчик в Python — одна строка в нужном месте:
breakpoint()Программа остановится, и ты окажешься в интерактивной оболочке, где можно
смотреть любые переменные. c — продолжить, n — следующая строка,
q — выйти.
Как сказать ИИ
Я не понимаю, почему здесь получается пустой список.
Куда поставить две печати, чтобы это стало видно?
Код не меняй, только скажи места и что печатать.Добавь отладочную печать во все три функции: метка,
ключевые значения через !r и их типы. Потом я уберу.И обязательный шаг в конце:
Убери всю отладочную печать, которую мы добавляли.
Логирование через log.* не трогай.На что смотреть
Печать осталась в коде. Классика: отладили, забыли убрать, оно уехало на
сервер и теперь засоряет вывод. Перед коммитом — поиск по print( в диффе.
Печать вместо логирования в долгоживущем коде. В боте или на сервере
print исчезает вместе с терминалом. Там нужен logging (статья 4.2).
Печатается не то место. Если вывод не меняется при явно разных входных данных, скорее всего, печать стоит не в той ветке кода — или до неё вообще не доходит.
Секреты в печати. print(config) вместе с токеном — и он в истории
терминала, а то и в скриншоте, отправленном в чат.
Шпаргалка
Метка в начале строки:
[parse] ....Всегда
!r— видно пробелы, кавычки,None.Печатай тип, а не только значение.
Словари — через
json.dumps(..., ensure_ascii=False)и срез.Не знаешь, что смотреть, —
breakpoint().Перед коммитом проверь дифф на оставшиеся
print(.