Вспомните: в уроке 4.1 вы выбрали задачу, описали её на одной странице и разложили программу на функции: логика живёт в своём модуле utils.py, а главный файл её только импортирует и вызывает. В уроке 3.4 вы собирали exe и искали settings.json через app_dir(). Теперь соединяем всё: в каком порядке доводить проект до exe, как проверить его до того, как он уйдёт к людям, что написать в README и что показать на защите.
🎯 После урока сможете: довести свою утилиту до exe в порядке «логика → командная строка → окно → exe», прогнать её по чек-листу готовности (ошибки ввода, пустая папка, кодировки, настройки рядом с exe), написать README на полстраницы и подготовить пятиминутную защиту. В конце урока — итоговый проект курса.
Порядок сборки: логика → командная строка → окно → exe
Сквозной пример — «Разборщик чеков»: в папке лежат выгрузки покупок в CSV, программа считает итоги по категориям. Ваш проект будет своим, порядок тот же. Каждый следующий слой опирается на предыдущий, и ошибку ищут только в новом слое: всё, что под ним, уже проверено.
- Логика. Функции в
utils.pyработают на маленьких данных и провереныassert— это вы сделали в уроке 4.1. Окна ещё нет. - Командная строка. Короткий
cli.pyпринимает папку черезargparseи печатает результат. Так программу проверяют на настоящих файлах за секунды, без щелчков мышью. - Окно.
okno.pyна Tkinter вызывает те же функции изutils.py. Если окно показывает не то, а командная строка на тех же данных — то, ошибка в окне. - Exe. Собираете окно через PyInstaller, как в уроке 3.4, и проверяете уже собранную программу.
Логика «Разборщика чеков» — тот самый utils.py из урока 4.1: parse_amount, read_rows, totals_by_category и save_report остаются как были, колонки те же — дата;категория;сумма. Командной строке и окну нужны ещё три короткие функции. Добавляем их в конец модуля, каждую со своей работой, и дописываем проверку в блок прямого запуска:
import csv
import json
import sys
from pathlib import Path
# ... parse_amount, read_rows, totals_by_category, save_report — как в уроке 4.1
def read_folder(folder):
"""Ввод: строки всех CSV-выгрузок из папки."""
rows = []
for path in sorted(Path(folder).glob("*.csv")):
rows.extend(read_rows(path))
return rows
def drop_bad_rows(rows):
"""Обработка: отсеивает строки, где сумма не читается числом."""
good = []
for row in rows:
try:
parse_amount(row["сумма"] or "")
except ValueError:
continue
good.append(row)
return good, len(rows) - len(good)
def app_dir():
"""Папка программы: рядом с exe после сборки, рядом с .py до неё."""
if getattr(sys, "frozen", False):
return Path(sys.executable).parent
return Path(__file__).parent
if __name__ == "__main__":
assert parse_amount("1 200,50") == 1200.5
assert parse_amount("99") == 99.0
rows = [{"категория": "Кафе", "сумма": "100"},
{"категория": "кафе ", "сумма": "50,5"},
{"категория": "такси", "сумма": "300"}]
assert totals_by_category(rows) == {"кафе": 150.5, "такси": 300.0}
assert totals_by_category([]) == {}
bad = rows + [{"категория": "кафе", "сумма": "—"}, {"категория": "кафе", "сумма": None}]
assert drop_bad_rows(bad) == (rows, 2)
print("utils.py: все проверки пройдены")
read_folder(folder)— ввод: читает все CSV папки. Этот цикл жил вmain.pyурока 4.1; теперь он нужен и командной строке, и окну, поэтому переехал в модуль — копировать его не придётся;drop_bad_rows(rows)— обработка: отсеивает строки, где сумма не читается числом, и возвращает хорошие строки и число пропущенных. Так выполняется пункт ТЗ «строка с плохой суммой пропускается и считается»:totals_by_categoryна такой строке упала бы сValueError;app_dir()— из урока 3.4: папка программы, чтобыotchet.jsonложился рядом с exe.
Слой командной строки — cli.py. Он заменяет main.py из урока 4.1 и, как он, только вызывает функции модуля; запуск — под if __name__ == "__main__"::
import argparse
from utils import app_dir, drop_bad_rows, read_folder, save_report, totals_by_category
def main():
parser = argparse.ArgumentParser(description="Итоги по чекам из папки")
parser.add_argument("papka", help="папка с выгрузками CSV")
args = parser.parse_args()
rows, skipped = drop_bad_rows(read_folder(args.papka))
if not rows:
print("В папке нет чеков")
return
totals = totals_by_category(rows)
save_report(totals, app_dir() / "otchet.json")
for category, total in sorted(totals.items()):
print(f"{category}: {total:.2f}")
print("Пропущено строк:", skipped)
if __name__ == "__main__":
main()
В папке vygruzki — две выгрузки из урока 4.1 и третья, 2026-09-c.csv, где в одной строке вместо суммы прочерк:
# vygruzki/2026-09-c.csv
дата;категория;сумма
2026-09-14;транспорт;120
2026-09-15;кафе;—
Запуск на этой папке и на пустой папке pusto:
> python cli.py vygruzki
кафе: 800.30
продукты: 3255.50
транспорт: 185.00
Пропущено строк: 1
> python cli.py pusto
В папке нет чеков
Итоги кафе и продуктов те же, что в уроке 4.1: третья выгрузка добавила 120 к транспорту, а строка с прочерком пропущена и посчитана. Рядом с cli.py появился otchet.json с теми же итогами.
Окно — okno.py — вызывает те же функции из обработчика кнопки. Сравните с cli.py: в окне нет ни одной строки про CSV и суммы, только выбор папки и показ результата:
import tkinter as tk
from tkinter import filedialog, messagebox
from utils import app_dir, drop_bad_rows, read_folder, save_report, totals_by_category
def vybrat_papku():
papka = filedialog.askdirectory()
if not papka:
return
rows, skipped = drop_bad_rows(read_folder(papka))
if not rows:
messagebox.showwarning("Чеки", "В папке нет чеков")
return
totals = totals_by_category(rows)
save_report(totals, app_dir() / "otchet.json")
stroki = [f"{kat}: {summa:.2f}" for kat, summa in sorted(totals.items())]
stroki.append(f"Пропущено строк: {skipped}")
messagebox.showinfo("Итоги", "\n".join(stroki))
def main():
root = tk.Tk()
root.title("Разборщик чеков")
tk.Button(root, text="Выбрать папку", command=vybrat_papku).pack(padx=40, pady=20)
root.mainloop()
if __name__ == "__main__":
main()
Окно здесь урезано до одной кнопки, чтобы было видно главное. В ТЗ из урока 4.1 у окна ещё список итогов и запоминание папки в settings.json — это делается так же, как в уроке 3.3.
Собирают главный файл окна. Модуль utils.py отдельно указывать не нужно: PyInstaller сам находит модули, которые импортирует скрипт, — как он нашёл json и pathlib в уроке 3.4.
python -m PyInstaller --onefile --windowed --name Cheki okno.py

Проверьте себя
Контрольный вопрос. Коллега сделал утилиту расходов в обход порядка: написал функции и сразу собрал exe из окна, без командной строки. Exe показывает неверный итог. Почему ошибку теперь трудно найти?
Подсказка: Какие слои успели доказать, что работают на настоящих файлах, до того как появился exe?
Онлайн-проверка ответа появится позже
Контрольный вопрос. В окне «Разборщика чеков» итог по категории «кафе» — 0, а та же папка через cli.py даёт верный итог. Где искать ошибку?
Подсказка: Какие слои уже доказали, что работают на этих данных? Что осталось непроверенным?
Онлайн-проверка ответа появится позже
Задание. Программа ниже разбирает строки «категория;сумма». Что она напечатает? Введите строку вывода целиком.
Исходный код для этого задания:
strok = ["продукты;450", "транспорт;3,2", "кафе;1200", "продукты;"] itogo = 0 oshibki = 0 for s in strok: kat, summa = s.split(";") try: itogo += float(summa) except ValueError: oshibki += 1 print(itogo, oshibki)Подсказка: Пройдите строки по одной: какие значения float() примет, а на каких выбросит ValueError? Помните, что float понимает только точку.
✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.
Онлайн-проверка ответа появится позже
Чек-лист готовности: что проверить до отправки
Программа, которая работает на ваших файлах, ещё не готова: у коллеги будут другие файлы, другая папка и другие ошибки. Перед сборкой и после неё пройдите пять пунктов. Каждый ловит свой сбой.
- Ошибки ввода. Сумма с запятой, прочерк, пустая ячейка, буквы в поле окна. Программа не падает:
try/except ValueError(урок 2.1), строка пропускается и учитывается, в окне —messagebox.showerror, а не трассировка. - Пустые данные. Пустая папка, папка без CSV, файл с одной шапкой. Программа говорит «нет чеков», а не делит на ноль и не печатает пустой отчёт. Проверьте
if not …до расчётов среднего и процентов. - Кодировки. Выгрузка из Excel приходит в
utf-8-sig(с меткой BOM) или вcp1251. Откройте файл каждой кодировки, которая встречается у вас, и поймайтеUnicodeDecodeError, если файл не читается. - Настройки и отчёт рядом с exe. Пути к
settings.jsonи к файлу отчёта — черезapp_dir()из урока 3.4, не относительные. Запустите собранный exe из другой папки. - Чистая машина. Запустите exe у коллеги или на компьютере без Python. Только там видно, что ничего не забыто.
Пустые данные проверяют маленькой функцией. Без проверки if not summy пустой список дал бы ZeroDivisionError:
def sredniy(summy):
if not summy:
return 0
return round(sum(summy) / len(summy), 1)
assert sredniy([]) == 0
assert sredniy([100, 200]) == 150.0
print("проверки пройдены")
проверки пройдены

Проверьте себя
Контрольный вопрос. Коллега открыл exe двойным щелчком — настройки подхватились. Запустил тот же exe из терминала, находясь в своей папке Документы, — программа работает со значениями по умолчанию. Какой пункт чек-листа ловит этот сбой?
Подсказка: От чего зависит относительный путь и что поменялось между двумя запусками?
Онлайн-проверка ответа появится позже
Контрольный вопрос. На выгрузке из банка программа падает с UnicodeDecodeError, на ваших тестовых файлах — нет. Какой пункт чек-листа ловит этот сбой?
Подсказка: Что означает слово Decode в названии ошибки: программа не поняла число или не смогла прочитать байты файла как текст?
Онлайн-проверка ответа появится позже
Контрольный вопрос. Пользователь выбрал в окне папку, где нет ни одного CSV, и программа упала с ZeroDivisionError при расчёте среднего чека. Какой пункт чек-листа ловит этот сбой?
Подсказка: Сколько сумм попало в расчёт и что тогда стоит в знаменателе?
Онлайн-проверка ответа появится позже
Задание. «Разборщик чеков» собран с —onefile в файл D:\Утилиты\cheki\cheki.exe. Его запустили из терминала, находясь в папке C:\Users\ученик. Чтение настроек сделано через app_dir() из урока 3.4. В какой папке программа будет искать settings.json? Введите полный путь к папке, без имени файла и без слеша в конце.
Исходный код для этого задания:
def app_dir(): if getattr(sys, "frozen", False): return Path(sys.executable).parent return Path(__file__).parent settings_path = app_dir() / "settings.json"Подсказка: Программа собрана, значит, какая ветка app_dir() сработает? На что указывает sys.executable в собранной программе?
✅ Готово, если: ты ввёл(а) верный ответ, и онлайн-проверка его приняла.
Онлайн-проверка ответа появится позже
Задание. Напишите функцию dolya(summa, vsego), которая возвращает долю категории в процентах, округлённую round() до одного знака, а если vsego равно 0 — возвращает 0 и не падает. Вызовите print(dolya(0, 0), dolya(380, 2030)). Введите строку, которую напечатает программа.
Исходный код для этого задания:
def dolya(summa, vsego): ... # ваш код print(dolya(0, 0), dolya(380, 2030))Подсказка: Сначала проверка пустого случая и return, потом расчёт: сумма делится на итог и умножается на 100.
✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.
Онлайн-проверка ответа появится позже
README на полстраницы
README — текстовый файл README.md или README.txt рядом с программой. Его читает человек, который видит вашу утилиту впервые: коллега, преподаватель, вы через полгода. Полстраницы хватает, если ответить на пять вопросов:
- Что делает — одно предложение.
- Что нужно на входе — какие файлы, в каком формате, пример строки.
- Как запустить — exe двойным щелчком или команда с параметрами.
- Что получится — куда ляжет отчёт и как он выглядит.
- Настройки и ограничения — где
settings.json, что программа не умеет, под какую систему собрана.
# Разборщик чеков
Считает итоги покупок по категориям по всем CSV в выбранной папке.
## Что нужно
CSV в UTF-8 с разделителем «;» и шапкой дата;категория;сумма,
например: 2026-09-02;Продукты;1 240,50
## Как запустить
Cheki.exe — двойной щелчок, кнопка «Выбрать папку».
Из терминала без окна: python cli.py путь_к_папке
## Что получится
Итоги по категориям на экране и файл otchet.json рядом с Cheki.exe.
«Кафе» и «кафе » — одна категория. Строки, где сумма не число,
пропускаются, их число показывается.
## Настройки и ограничения
settings.json рядом с Cheki.exe. Собрано под Windows 10,
на macOS не запустится. Антивирус может спросить разрешение.
Проверьте себя
Контрольный вопрос. Ниже README чужого проекта. Чего в нём не хватает, чтобы коллега смог воспользоваться программой?
# Сортировщик фото
Раскладывает фотографии из папки по подпапкам год/месяц
по дате съёмки.
## Что получится
В выбранной папке появятся подпапки вида 2026/09.
## Ограничения
Собрано под Windows. Видео не трогает.
Подсказка: Пройдите по пяти вопросам README из урока и отметьте, на какие этот текст отвечает.
Онлайн-проверка ответа появится позже
Защита проекта: пять минут
Защита проходит на занятии: вы показываете проект преподавателю и группе. Если вы проходите курс без группы, запишите экран на 3–5 минут по тому же плану и приложите запись к сдаче. Не пересказывайте код построчно — его смотрят по вложению. Пять минут делятся так:
- Задача (1 минута). Какую свою рутину программа убирает и сколько времени она занимала руками.
- Демонстрация (2–3 минуты). Запуск exe или командной строки на примере входа — копии ваших данных, где настоящие значения заменены выдуманными: вход → результат, который совпадает со строкой «Готово, когда» из ТЗ. Затем один плохой случай из чек-листа — пустая папка или кривая строка — и как программа на него отвечает.
- Одна трудность (1 минута). Что не получалось, как нашли причину, как решили. Это самая ценная минута: по ней видно, что проект ваш.
После — вопросы. Типичные: почему эта функция живёт в utils.py, что будет, если подать другой файл, где программа ищет настройки после сборки. Если exe не собрался — расскажите, на каком шаге и с какой ошибкой: честный разбор в README даёт половину баллов за сборку.
На защите и во вложении — только код, README, ТЗ, пример входа и скриншоты. Свои настоящие выгрузки, чеки и личные файлы не прикладывайте и не показывайте на общем экране: для демонстрации сделайте копию с выдуманными значениями — это и будет пример входа.

Проверьте себя
Контрольный вопрос. Какой план пятиминутной защиты соответствует уроку?
Подсказка: Из каких трёх частей состоят пять минут и что в них показывают вместо кода?
Онлайн-проверка ответа появится позже
Итоговый проект: своя утилита
Итоговая работа курса — ваша утилита для вашей рутины, от задумки урока 4.1 до exe. «Разборщик чеков» — образец, а не обязательная тема: подойдёт сортировщик файлов, сводка по журналу, переименование фото, отчёт по таблице — любая задача, где есть данные и проверяемый результат. Проект проверяет преподаватель по критериям из условия задания, балл — их сумма, максимум 15, зачёт — от 9.
Задание. Итоговый проект «Своя утилита». Сделайте программу для своей рутины по порядку урока: ТЗ на одну страницу → логика в своём модуле с проверками assert → интерфейс → exe. Интерфейс — одно из двух, по вашей задаче: окно Tkinter или командная строка с параметрами argparse. Пройдите чек-лист готовности и напишите README.
Что сдать: один архив .zip с проектом:
— ТЗ на одну страницу (TZ.md или TZ.txt) из пяти частей урока 4.1. В строке «Готово, когда» укажите пример входа из архива и результат, посчитанный вручную;
— все файлы .py: модуль с логикой и главный файл;
— README;
— пример входного файла с выдуманными данными (3–10 строк);
— скриншот окна или терминала с результатом;
— если exe собран — скриншот папки dist с exe и скриншот запущенного exe; если не собран — разбор в README: на каком шаге, с какой ошибкой и почему.
Сам exe и папки build/dist в архив не кладите. Свои настоящие файлы и личные данные не прикладывайте.Защита: на занятии — 5 минут: какую рутину убирает программа; показ на примере входа (копия ваших данных с выдуманными значениями) и одного плохого случая из чек-листа; одна трудность и её решение; затем вопросы преподавателя. Если проходите курс без группы — запись экрана на 3–5 минут по тому же плану: файл в архиве или ссылка в ответе.
Как оценят (15 баллов):
1. ТЗ на одну страницу: есть все пять частей — вход, выход, ошибки, интерфейс, «Готово, когда»; 1 — все пять на месте, 0 — хоть одной нет — 1 балл.
2. Верный результат: на примере входа из «Готово, когда» программа выдаёт результат, записанный в ТЗ; 2 — совпадает полностью, 1 — совпадает частично (часть файлов или итогов), 0 — не совпадает или не запустилась — 2 балла.
3. Плохие данные не роняют программу (проверяется на защите): 2 — и ошибка ввода (кривая строка, буквы в поле), и пустой вход (пустая папка или пустой файл) дают понятное сообщение вместо трассировки; 1 — только один из двух случаев; 0 — оба падают — 2 балла.
4. Логика в своём модуле: в главном файле (cli.py, окно или main.py) нет расчётов, только вызовы функций модуля — 1 балл.
5. Одна функция — одна работа: каждую функцию модуля можно назвать одним глаголом без «и» — 1 балл.
6. Проверки assert в модуле под if __name__ == «__main__»: запуск модуля напрямую проходит их без ошибок — 1 балл.
7. Интерфейс по задаче — одно из двух: окно Tkinter или командная строка с параметрами argparse — 1 балл.
8. Настройки или отчёт сохраняются в JSON или CSV, путь — через app_dir() — 1 балл.
9. Exe: 2 — собран и запускается (скриншот папки dist с exe и скриншот запущенной программы); 1 — не собран, но в README разобраны шаг, текст ошибки и причина (macOS, антивирус и т. п.); 0 — ни того ни другого — 2 балла.
10. README отвечает на пять вопросов: что делает, вход, запуск, результат, настройки и ограничения — 1 балл.
11. Защита по плану из трёх частей: какую рутину убирает программа, показ на примере входа вместе с плохим случаем, рассказ об одной трудности и её решении — 1 балл.
12. Ответы на вопросы: объясняет, зачем в его коде любая функция, на которую укажет преподаватель — 1 балл.Зачтено — от 9 баллов из 15, при этом за «Верный результат» не 0.
Онлайн-проверка ответа появится позже
Что дальше
Теперь вы умеете доводить свою программу до exe по слоям — логика, командная строка, окно, сборка, — проверять её по чек-листу готовности, писать README, по которому ею может пользоваться другой человек, и защищать проект за пять минут. Курс «Python для своих задач» пройден: у вас есть утилита, которая экономит ваше время и запускается у людей без Python. Вернитесь к навигатору курса, если захотите повторить тему, к которой привязан ваш проект.
← Назад · ↑ В начало урока · ⌂ К навигатору курса · Вперёд →
