CLI-интерфейс и обработка ошибок
CLI-интерфейс и обработка ошибок
Бизнес-логика готова: классы Contact и AddressBook работают и сохраняют данные. Последний шаг — создать интерфейс командной строки, с которым будет взаимодействовать пользователь. Это превратит набор классов в готовое приложение.
Структура CLI: цикл с меню
Консольные приложения работают по одной схеме: показать меню → получить команду → выполнить → повторить:
# cli.py
from address_book import AddressBook
from contact import Contact, ContactNotFoundError
def show_menu():
print("\n=== Телефонная книга ===")
print("1. Показать все контакты")
print("2. Добавить контакт")
print("3. Найти контакт")
print("4. Удалить контакт")
print("0. Выход")
def run_cli(book: AddressBook):
while True:
show_menu()
choice = input("Выберите действие: ").strip()
if choice == "0":
print("До свидания!")
break
elif choice == "1":
cmd_list(book)
elif choice == "2":
cmd_add(book)
elif choice == "3":
cmd_find(book)
elif choice == "4":
cmd_delete(book)
else:
print("Неизвестная команда")
Функции команд
Каждая команда — отдельная функция. Это делает код читаемым и позволяет легко добавлять новые команды:
def cmd_list(book: AddressBook):
contacts = book.all()
if not contacts:
print("Книга пуста")
return
print(f"\nКонтактов: {len(contacts)}")
for c in contacts:
print(f" {c}")
def cmd_add(book: AddressBook):
name = input("Имя: ").strip()
phone = input("Телефон: ").strip()
email = input("Email (Enter — пропустить): ").strip() or None
try:
contact = Contact(name, phone, email)
book.add(contact)
print(f"Контакт '{contact.name}' добавлен")
except ValueError as e:
print(f"Ошибка: {e}")
def cmd_find(book: AddressBook):
query = input("Имя для поиска: ").strip()
results = book.search(query)
if not results:
print("Ничего не найдено")
else:
for c in results:
print(f" {c}")
def cmd_delete(book: AddressBook):
name = input("Имя для удаления: ").strip()
try:
book.delete(name)
print(f"Контакт '{name}' удалён")
except ContactNotFoundError as e:
print(f"Ошибка: {e}")
Точка входа: main.py
# main.py
from address_book import AddressBook
from cli import run_cli
CONTACTS_FILE = "contacts.json"
def main():
book = AddressBook(CONTACTS_FILE)
run_cli(book)
if __name__ == "__main__":
main()
Принципы обработки ошибок в CLI
Хороший CLI не падает от ошибок пользователя:
-
Ожидаемые ошибки перехватывай — пустое имя, несуществующий контакт — это предсказуемые ситуации, они перехватываются и выводятся понятным сообщением.
-
Неожиданные ошибки позволяй всплывать — баги в коде (не в вводе пользователя) должны быть видны: не прячь их в
except Exception: pass. -
KeyboardInterrupt обрабатывай gracefully — если пользователь нажал Ctrl+C, завершись корректно:
# main.py
def main():
book = AddressBook(CONTACTS_FILE)
try:
run_cli(book)
except KeyboardInterrupt:
print("\nПрервано пользователем. До свидания!")
Итоговая структура проекта
phonebook/
contact.py — Contact, ContactNotFoundError
address_book.py — AddressBook (хранение, поиск, CRUD)
cli.py — show_menu, run_cli, cmd_*
main.py — точка входа, CONTACTS_FILE
contacts.json — создаётся автоматически при первом запуске
Запуск: python main.py
Что дальше
Телефонная книга готова! Её можно расширить:
- Поиск по телефону или email
- Редактирование существующего контакта
- Экспорт в CSV
- Сортировка по разным полям
- Группы контактов
Каждое расширение — один-два новых метода в AddressBook и новая команда в cli.py. Архитектура позволяет расти без переписывания существующего кода.
Итог
- Цикл с меню — стандартный паттерн для консольных приложений.
- Одна функция = одна команда;
run_cliтолько маршрутизирует. - Ожидаемые ошибки перехватываем (
ValueError,ContactNotFoundError) и показываем сообщение. KeyboardInterruptобрабатываем gracefully вmain().if __name__ == "__main__":гарантирует, чтоmain()вызывается только при прямом запуске.
Поздравляем с завершением курса «Основы Python»! За 13 модулей вы прошли путь от print("Hello") до полноценного объектно-ориентированного приложения с файловым хранилищем. Python — инструмент, а мастерство приходит с практикой. Пишите код!