📜 Как показано в исходном материале
Исходная лекция использует простые конструкции try/except с выводом сообщений через print:
# из исходника
try:
result = 10 / 0
except ZeroDivisionError:
print("Ошибка: деление на ноль!")
Этот код корректен и понятен, но в реальных программах его стоит дополнить логированием и более точной обработкой.
❌ Что можно улучшить
- Общий
except Exception:или «голый»except:перехватывают слишком много, включая системные исключения. - Простой
printне сохраняет историю ошибок — в production важны логи. - Блок
tryчасто содержит лишний код, который не должен обрабатываться как ошибка. - Ресурсы (файлы, соединения) лучше освобождать через
with, а не вручную вfinally.
✅ Рекомендуемый современный вариант
# modern_safe_divide.py
import logging
logging.basicConfig(
filename="errors.log",
format="%(asctime)s - %(filename)s - %(lineno)d - %(levelname)s - %(message)s",
level=logging.ERROR,
)
def safe_divide(a: float, b: float) -> float:
if b == 0:
raise ValueError("Делитель не может быть нулём")
return a / b
try:
dividend = float(input("Введите делимое: "))
divisor = float(input("Введите делитель: "))
result = safe_divide(dividend, divisor)
except ValueError as e:
logging.error(f"Ошибка: {e}")
print(f"Ошибка: {e}")
else:
print(f"Результат: {result}")
Что улучшилось:
- Guard clause внутри функции явно проверяет делитель.
- Конкретное исключение
ValueErrorвместо общегоException. - Логирование сохраняет ошибку в файл.
elseотделяет успешный сценарий от обработки ошибок.
Современный подход к файлам
with для работы с файлами не разбирается в исходной лекции, но является рекомендуемым способом гарантировать закрытие ресурса.
# modern_file_handling.py
# Читаем числа из файла и суммируем их.
filename = "numbers.txt"
total = 0
try:
with open(filename, "r", encoding="utf-8") as file:
for line in file:
total += float(line.strip())
except FileNotFoundError:
print(f"Файл {filename} не найден.")
except ValueError as e:
print(f"Некорректная строка: {e}")
else:
print(f"Сумма: {total}")
Конструкция with автоматически закрывает файл даже при исключении, заменяя try/finally.
EAFP вместо LBYL
В Python часто предпочитают стиль EAFP (Easier to Ask for Forgiveness than Permission) — проще попросить прощения, чем разрешения. Вместо множества предварительных проверок делаем действие и ловим ожидаемое исключение:
# eafp_example.py
info = {"a": 1}
# LBYL: много проверок
if "b" in info:
print(info["b"])
else:
print("Ключа b нет")
# EAFP: проще и понятнее
try:
print(info["b"])
except KeyError:
print("Ключа b нет")
Оба подхода допустимы, но в Python EAFP часто читается лучше и работает быстрее для встроенных типов.
🕰️ Когда старый подход ещё можно встретить
Учебные примеры и быстрые скрипты часто используют print и простые try/except. Это нормально для демонстрации, но в домашних заданиях и реальных проектах стоит применять конкретные исключения, логирование и guard clauses.