Домашнє завдання

Помилки та винятки

Заведи для цього завдання окрему теку — хай буде dz18/ — і працюй у ній. Скрізь, де просять «навмисно зламати», зберігай повний traceback текстом: він і є доказом того, що ти зробив.


рівень 1Рівень 1 — База

Напиши файл kalkulyator.py з функцією podilyty(a, b), яка повертає a / b.

  1. Обгорни ділення в try / except із конкретним типом: при діленні на нуль функція має повертати рядок "на нуль ділити не можна", а не падати.
  2. Додай другу гілку except TypeError, яка повертає "аргументи мають бути числами" — вона спрацює, якщо передати рядок.
  3. Додай блок finally, який дописує +1 до глобального лічильника викликів.
  4. У кінці файлу, під if __name__ == "__main__":, постав перевірки:

python assert podilyty(10, 2) == 5.0 assert podilyty(10, 0) == "на нуль ділити не можна" assert podilyty("десять", 2) == "аргументи мають бути числами" assert викликів == 3, "finally мав спрацювати на кожен виклик" print("✅ рівень 1")

Зроблено, якщо: python3 kalkulyator.py друкує ✅ рівень 1 і більше нічого; у файлі немає жодного голого except: і жодного except Exception.


рівень 2Рівень 2 — Плюс

Візьми битий прайс і доведи на числах, чим голий except шкідливий.

  1. Створи файл prays.txt із шістьма рядками формату назва;ціна, з яких три зіпсовані по-різному: ціна словами, немає крапки з комою, порожня назва. (Читати файл ще не вчились — просто поклади ті самі рядки в список у коді, а prays.txt хай буде довідкою для тебе.)
  2. Напиши два варіанти обробника прайсу в одному файлі porivnyannya.py:
  3. rozibraty_goliy(ryadok) — з except: без типу;
  4. rozibraty_tochno(ryadok) — з except (ValueError, IndexError).
  5. Тепер зроби в обох функціях однаковий одрук: напиши flot замість float. Запусти обидві на всьому прайсі й запиши в sposterezhennya.md:
  6. що надрукувала кожна версія;
  7. яку суму дала кожна;
  8. traceback, який показала точна версія.
  9. Поверни float на місце й переконайся, що тепер обидві версії дають однакову суму. Додай assert, який це фіксує.

Зроблено, якщо: у sposterezhennya.md є (а) дві різні суми з одруком, (б) traceback зі словом NameError, (в) абзац своїми словами про те, чому різниця в одному слові після except коштує стільки; а python3 porivnyannya.py у виправленій версії відпрацьовує без помилок і друкує пройдений assert.


рівень 3Рівень 3 — Виклик

Побудуй власну ієрархію винятків і доведи, що вона поводиться як дерево.

  1. У файлі vynyatky.py опиши три типи:

PomylkaPraysu(Exception) ├── PomylkaCiny — ціна не число або відʼємна └── PomylkaFormatu — рядок не розкладається рівно на дві частини

  1. У файлі rozbir.py напиши rozibraty(ryadok), яка кидає точний підтип у кожному випадку й обовʼязково зберігає первинну причину через from e.
  2. Доведи assert-ами всі чотири твердження:
  3. except PomylkaCiny ловить помилку ціни й не ловить помилку формату;
  4. except PomylkaPraysu ловить обидві;
  5. except Exception теж ловить обидві;
  6. except KeyboardInterrupt не ловить жодної.
  7. Заміряй довжину traceback у рядках для трьох варіантів підняття на одному й тому самому зіпсованому рядку: raise X(...), raise X(...) from e, raise X(...) from None. Підказка: traceback.format_exc() повертає звіт рядком. Запиши три числа в tracebacks.md і поясни, чому два з них однакові, а третє менше.
  8. Додай у rozbir.py функцію obrobyty(ryadky), яка повертає три списки: ciny, skargy (очікувані PomylkaPraysu) і avarii (усе інше). Перевір її на списку, де один елемент — не рядок, а число 42, і доведи assert-ом, що це число опинилось саме в avarii.

Зроблено, якщо: python3 rozbir.py відпрацьовує без помилок; усі assert з пунктів 3 і 5 мовчать; у tracebacks.md є три числа й абзац пояснення, у якому названо, що саме додає до звіту неявний ланцюжок.


Підказки