Модуль 5 · Урок 19 із 58
Exceptions: вузький handler і чесний failure
Exception — не незручність, яку треба приховати, а typed signal, що normal contract не може бути виконаний. Хороший handler знає, яку конкретну failure він може відновити або перекласти; усі інші exceptions мають зберегти traceback і дійти до boundary, де програма завершиться чесно.
Безпечна практика модуля 5
Пакет містить тільки synthetic JSON/CSV, explicit UTF-8, schema validation, deterministic output, safe logging і локальні tests. Жодних персональних чи production-даних, secrets, мережевих викликів або зовнішніх залежностей.
SyntaxError і runtime exception — різні етапи
Parser зупиняє invalid syntax до normal execution. Runtime exceptions виникають під час операції: FileNotFoundError, UnicodeDecodeError, json.JSONDecodeError, ValueError. Handler має відповідати реальному failure type, а не ловити все «про всяк випадок».
Try block має бути вузьким
try:
text = path.read_text(encoding="utf-8")
except FileNotFoundError as exc:
raise InputError(f"missing input: {path.name}") from exc
else:
return parse_records(text)У try лишається operation, whose exception ви очікуєте. Parsing винесено в else, тому його bug не буде помилково оголошений «missing file». from exc зберігає causal chain для diagnosis, водночас public message може бути коротким.
Не ковтайте Exception
# Погано: приховує bugs і interrupts
try:
run()
except Exception:
passBroad catch без re-raise перетворює failure на неправдивий success. Якщо top-level CLI ловить Exception для final log, він має повернути non-zero exit і не називати partial output готовим. KeyboardInterrupt та SystemExit не є subclasses Exception, і не треба маскувати user cancellation.
else і finally мають окремий сенс
else виконується лише якщо try завершився без exception; він зменшує зону accidental catching. finally виконується незалежно від result і підходить для cleanup, але return у finally може приховати активну exception — цього слід уникати. File lifecycle зазвичай простіше виразити через with.
Custom exception — стабільний interface між layers
class InputError(Exception):
"""Expected user-correctable input failure."""
def main() -> int:
try:
build_report()
except InputError as exc:
print(f"error: {exc}", file=sys.stderr)
return 2
return 0Adapter може перекласти low-level exceptions у domain-level InputError. Не створюйте class для кожної фрази; custom type корисний, коли caller має окрему behavior policy. Public error не повинен друкувати absolute paths, secrets або entire customer row.
Failure matrix і tests
| Case | Expected signal | Output contract |
|---|---|---|
| Missing input | InputError / exit 2 | No report |
| Invalid UTF-8 | InputError із safe reason | No partial report |
| Malformed JSON | InputError + chained cause | Line/column, no payload dump |
| Programmer bug | Unhandled traceback in dev | Non-zero, no false success |
Definition of Done
- Expected failures мають specific exception types.
- Try blocks не охоплюють unrelated code.
- Cause збережено через chaining, коли exception перекладається.
- CLI success/failure відображено exit status.
- Logs/messages не приховують bug і не витікають sensitive values.
Методичні джерела
Урок, сценарії, пояснення й вправи створені SEOWORK. Посилання ведуть лише на офіційну документацію Python.
Закріпіть матеріал уроку
Три сценарні питання. Для зарахування уроку потрібно дати щонайменше дві правильні відповіді.