Среда программирования. Методы отладки.
10 класс, углублённый уровень — занятие второе.
В прошлый раз мы писали программы. Сегодня — про то, что происходит между вашим текстом и процессором, и что делать, когда программа работает не так, как задумано.
printОн понимает только числа — машинный код.
print("Привет") # так пишете вы
b8 21 0a 00 00 e8 f4 ... # так это выглядит для процессора
Переводит всю программу заранее, до запуска. На выходе — готовый файл, который дальше работает сам.
C, C++, Pascal
Переводит и выполняет по ходу дела, строку за строкой. Отдельного файла не остаётся.
Python, JavaScript
| Компилятор | Интерпретатор | |
|---|---|---|
| Скорость работы | выше | ниже |
| Когда видно ошибку | до запуска, все сразу | когда до неё дошло выполнение |
| Перенос на другую систему | перекомпилировать | просто скопировать |
print("первая строка")
print("вторая строка")
print(10 / 0)
print("третья строка")
первая строка
вторая строка
ZeroDivisionError
Две строки успели напечататься: интерпретатор дошёл до третьей и только там споткнулся.
Не напечатал бы ничего.
Он проверяет программу целиком до запуска — до печати дело бы просто не дошло.
Текст → байт-код → виртуальная машина → процессор
__pycache__, чтобы
в следующий раз не переводить заново.__pycache__ лежат файлы
.pyc — открывать их текстовым редактором бесполезно,
они не для людей.
Байт-код одинаков везде, а виртуальные машины написаны под каждую систему. Программа переезжает с Windows на Linux и на телефон без единой правки.
Скоростью. Между программой и процессором стоит лишний слой, и тяжёлые вычисления на Python идут в десятки раз медленнее, чем на C++.
Так же устроены Java (виртуальная машина JVM) и C# (платформа .NET). Это не выдумка Python, а общий приём.
IDLE, в которой вы работаете, — тоже IDE, просто самая скромная.
F5, не выходя из редактора;PyCharm, VS Code, Visual Studio отличаются от IDLE удобствами, а не сутью. Программу выполняет всё тот же интерпретатор Python.
Самая частая и самая неприятная ситуация.
Красный текст, SyntaxError,
ValueError, TypeError.
Лечится чтением. Последняя строка сообщения говорит, что именно случилось и в какой строке.
Ошибок нет, программа что-то печатает — и это «что-то» неверное.
Python здесь молчит. Он выполнил ровно то, что написано. Написано не то, что задумано.
Компьютер не нужен. Нужен лист бумаги.
s = 0
for i in range(1, 5):
s = s + 2 * i
print(s)
| шаг | i | s |
|---|---|---|
| 1 | 1 | 2 |
| 2 | 2 | 6 |
| 3 | 3 | 12 |
| 4 | 4 | 20 |
По столбцам — переменные, по строкам — шаги цикла. Одна строка = один проход. Заполняя её, вы работаете процессором.
Программа должна сложить пробег за смену. А складывает неправильно.
n = int(input())
for i in range(n):
total = 0
km = int(input())
total = total + km
print(total)
Три поездки: 12, 5, 20. Ведём таблицу — и смотрим на
total в начале каждого шага:
| шаг | km | total в начале | total в конце |
|---|---|---|---|
| 1 | 12 | 0 | 12 |
| 2 | 5 | 0 | 5 |
| 3 | 20 | 0 | 20 |
Временный print там, где хочется посмотреть.
for i in range(n):
km = int(input())
total = total + km
print("шаг", i, "прочитал", km, "накопил", total) # временно!
Ничего не надо настраивать. Работает всегда и везде — в любой среде, на любом компьютере.
Забытая строка = неверный ответ. Оболочка сравнивает вывод с эталонным; лишняя строка — это уже другой вывод.
Он не находит ошибку. Он показывает, что происходит на самом деле.
Debug → Debugger;F5 в окне программы — она встанет на первой строке;Правой кнопкой по строке → Set Breakpoint. Строка станет
жёлтой. Теперь Go домчит программу до неё и остановится
перед этой строкой.
n = int(input())
total = 0
for i in range(n):
km = int(input())
total = total + km # сюда точку останова
print(total)
Жмём Go три раза подряд и каждый раз смотрим в Locals. Видно не одно значение, а как оно меняется: 12 → 17 → 37. Если бы накопитель обнулялся, мы увидели бы 12 → 5 → 20.
Работает и не заканчивается — значит, цикл не может выйти.
Ctrl+C в окне Shell.
Python напечатает KeyboardInterrupt и покажет строку,
на которой его прервали, — она внутри вечного цикла.free = limit
while free >= weight:
count = count + 1 # free не меняется никогда
Четыре задачи на трассировку: заполнить таблицу, сказать, сколько раз выполнится цикл, что выведет программа, и найти ошибку в чужой таблице.
Считаем в уме и на бумаге. Запустить — значит узнать ответ, но не научиться.
broken1.py, broken2.py,
broken3.py в общей папке. В каждой описано, что она
должна делать, и есть ровно одна ошибка.
Чиним и сохраняем в свою папку как zadanie1.py …
zadanie3.py.
| Что | Где | Сколько |
|---|---|---|
| Тренажёр трассировки | практикум, наверху страницы | 20 минут |
| Три починки | IDLE, файлы из общей папки | 20 минут |
| Проверка | Проверка.bat |
попыток сколько угодно |
File → Save As… в свою папку, и работать уже там.
Открывайте практикум. Начинаем с тренажёра.
Застряли на починке — не угадывайте. Возьмите лист и пройдите программу по шагам: три строки таблицы обычно решают дело.