Домашний проект F: приложение «Заметки»
Файлы и Tkinter вместе — но чтение и запись вынесены в функции, которые ничего не знают об интерфейсе.
Последний домашний проект объединяет файлы (глава 15) и Tkinter: приложение «Заметки» с текстовым полем и кнопками сохранить, загрузить, очистить. Работа с файлом вынесена в отдельные функции, не знающие о существовании Tkinter вовсе:
def sohranit_v_fajl(put: Path, tekst: str) -> None:
put.write_text(tekst, encoding="utf-8")
def zagruzit_iz_fajla(put: Path) -> str:
if not put.exists():
raise FileNotFoundError(put)
return put.read_text(encoding="utf-8")
sohranit_v_fajl() и zagruzit_iz_fajla() принимают обычный Path и не обращаются ни к одному виджету — тест может вызвать их во временном каталоге pytest, без единого окна на экране.Обработка ошибок и несохранённые изменения
Интерфейсный слой ловит конкретные исключения, а не пытается угадать, что пошло не так, — и предупреждает, если попытаться загрузить файл поверх ещё не сохранённого текста:
def zagruzit_zametku() -> None:
if est_nesohranennye_izmeneniya.get():
status_text.set("Есть несохранённые изменения — сначала сохраните или очистите поле")
return
try:
tekst = zagruzit_iz_fajla(fajl_zametok)
except FileNotFoundError:
status_text.set("Файл заметки ещё не создан — сначала сохраните.")
return
except (PermissionError, OSError) as oshibka:
status_text.set(f"Не удалось загрузить: {oshibka}")
return
Полный код: projects/tkinter/notes-app/notes_app.py
Задание
Добавьте кнопку «Сохранить как», открывающую filedialog.asksaveasfilename() и сохраняющую текст в выбранный пользователем файл.
Issue «Add notes app project», ветка feat/notes, тест на
сохранение и загрузку через временный файл (round-trip в UTF-8) и на
FileNotFoundError при отсутствующем файле, Pull Request.
Итоги приложения
Что мы повторили на шести проектах
- Безопасный разбор арифметики через ast — вместо eval(), даже ограниченного.
- Проверяемая случайность: генератор random.Random передаётся явно, а не берётся из глобального состояния модуля random.
- Таблица правил вместо цепочки условий — и полная проверка всех возможных комбинаций.
- Движение по delta time: скорость в пикселях в секунду, а не в пикселях за кадр.
- Проверка физических ограничений (температура не бывает ниже абсолютного нуля) — не только формальный ввод-вывод чисел.
- Файловые операции отдельно от интерфейса — с конкретной обработкой FileNotFoundError, PermissionError и OSError, а не общим except Exception.
- Каждый проект — тот же рабочий процесс, что и у SafeSort: Issue, ветка, тесты, коммит, Pull Request.