Українська
Валідація, ресурси та журналювання
Валідація, інваріанти й очищення ресурсів
LBYL (look before you leap) – спочатку перевірити умову, потім виконати дію. Наприклад, перевірити додатність кількості перед розрахунком. EAFP (easier to ask forgiveness than permission) – спробувати операцію та обробити очікувану відмову. int(text) із except ValueError є прикладом EAFP. Ці підходи доповнюють один одного: правильний числовий формат не гарантує дозволений діапазон, а допустимий діапазон не пояснює, як прочитати число.
Для ресурсів попередньої перевірки недостатньо: між перевіркою існування файла й відкриттям його може видалити інший процес. Тому обробляйте помилку саме під час відкриття. Конструкція with викликає протокол завершення роботи з ресурсом; для файла це забезпечує закриття і при помилці читання. Деталі файлів і менеджерів контексту будуть у наступних темах.
contextlib.suppress(FileNotFoundError) придатний для вузького випадку: відсутність необов’язкового тимчасового файла при видаленні є прийнятною. Не пригнічуйте Exception навколо обчислення, яке має видати результат. Відсутність повідомлення ще не означає успіху. Довідка: https://docs.python.org/3.14/library/contextlib.html#contextlib.suppress.
Інваріант – властивість, яку алгоритм має зберігати, наприклад невід’ємний лічильник оброблених елементів. assert condition перевіряє таке припущення розробника і піднімає AssertionError, якщо воно хибне. Запуск із -O вилучає перевірки assert. Тому перевірка введення, права доступу чи фінансового ліміту повинна використовувати if та відповідний raise.
py
def checked_square(number: int) -> int:
if number < 0:
raise ValueError("потрібне невід’ємне число")
result = number * number
assert result >= 0, "порушено інваріант квадрата"
return result
print(checked_square(7))49Порівняйте звичайний запуск та python -O square.py: число -1 має спричиняти ValueError в обох режимах. Не виконуйте потрібні дії всередині assert, наприклад виклик запису файла: в режимі оптимізації зникне і сама дія.
Помилка очищення
return усередині finally може перекрити попередній результат і навіть пригнітити виняток. Python 3.14 попереджає про такі виходи через SyntaxWarning. Звільняйте ресурси в finally, а рішення про результат залишайте основному алгоритму.
Журналювання подій
print призначений насамперед для результату й діалогу з користувачем. Модуль logging зберігає діагностичні події з рівнем важливості. DEBUG містить подробиці обчислення, INFO – звичайні події, WARNING – нетиповий, але допустимий стан, ERROR – невдалу операцію, CRITICAL – серйозний збій застосунку. Рівень INFO відсікає DEBUG, але пропускає решту названих рівнів.
getLogger(__name__) створює або повертає логер поточного модуля. basicConfig налаштовують на початку програми один раз. Зазвичай цей виклик нічого не змінює, якщо кореневий логер уже має обробники. У навчанні запускайте кожний приклад окремим процесом, щоб попередня конфігурація інтерактивної консолі не впливала на результат. Довідка: https://docs.python.org/3.14/howto/logging.html.
Для файла достатньо таких параметрів. Код створює events.log у поточному робочому каталозі, дописуючи повідомлення при наступних запусках. encoding="utf-8" зберігає українські літери.
py
import logging
logging.basicConfig(filename="events.log", encoding="utf-8",
level=logging.INFO,
format="%(levelname)s: %(message)s")
logger = logging.getLogger(__name__)
logger.debug("Подробиці обчислення")
logger.info("Розпочато перевірку")
try:
int("abc")
except ValueError:
logger.exception("Не вдалося прочитати число")На екран цей приклад нічого не друкує. У файлі є INFO, ERROR і traceback з кінцевим ValueError; рядка DEBUG немає. logger.exception треба викликати під час обробки винятку: він додає поточну діагностику до повідомлення рівня ERROR. Запис logger.error("...") без exc_info друкує лише повідомлення.
У форматі повідомлення логера зручно використовувати %s і окремі аргументи: logger.info("Залишок: %s", balance). Це дозволяє логеру відкласти форматування. Журнал пояснює, що сталося, але не змінює потік виконання: після logger.error програма продовжується, якщо ви окремо не підняли виняток або не завершили дію.