Уяви собі веб-додаток без обробки помилок. Користувач вводить навмисно некоректний запит, а замість дружнього повідомлення про помилку бачить стек викликів Python. Звучить лячно, правда? Неправильна або, що ще гірше, забута обробка помилок може зробити твій додаток не тільки незручним для користувачів, але й небезпечним.
Помилка в коді — це як несподіваний гість: іноді її можна ігнорувати, іноді — треба терміново латати наслідки її візиту, а іноді — краще підготуватися заздалегідь, щоб вона не була зовсім несподіванкою. У випадку веб-розробки грамотно налаштована обробка помилок допомагає:
- Покращити досвід користувача. Ми не хочемо, щоб користувачі бачили некрасиве повідомлення "500 Internal Server Error", коли можна показати інформативне повідомлення типу "Запитуваний ресурс не знайдено".
- Забезпечити безпеку. Вивід необроблених помилок може містити деталі реалізації додатку, які можуть бути використані зловмисником.
- Спростити налагодження. Логування помилок і розумний підхід до обробки допомагають швидко знаходити і виправляти баги.
Приклади помилок
Помилки бувають різні:
- Передбачувані помилки. Наприклад, користувач відправляє форму без заповнення обов'язкового поля, і наша логіка валідації коректно обробляє це.
- Непередбачувані помилки. Наприклад, база даних "упала", або стороннє API перестало відповідати — такі проблеми ми не завжди можемо передбачити, але все одно можемо підготуватися, щоб мінімізувати шкоду.
Якщо твій додаток зовсім не обробляє помилки, то він працює як якийсь капітан Титаніка — намагається плисти далі, незважаючи на айсберг попереду.
Основні принципи обробки помилок
Давай виділимо кілька перевірених принципів, які застосовують при обробці помилок.
Повідомлення користувачу
Перше і головне правило: користувач має бути в курсі, що щось пішло не так. Якщо запит виконується повільно і раптом кидає помилку, користувачу важливо розуміти причину. Наприклад, при спробі замовити товар користувач побачить повідомлення на кшталт "На жаль, цей товар більше недоступний", а не загадкове "Помилка 500".
У FastAPI ми можемо використовувати вбудовані механізми повернення HTTP-статусів і повідомлень. Наприклад, повернемо 404 код, якщо запитуваний ресурс не знайдено.
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id > 10: # Припустимо, що у нас тільки 10 предметів
raise HTTPException(status_code=404, detail="Item not found")
return {"item_id": item_id}
Коли користувач запитує ресурс, якого немає, він побачить JSON-відповідь:
{
"detail": "Item not found"
}
Логування помилок
Логування — це наш вірний друг-розробник. Воно не лише допомагає швидко знаходити баги, а й фіксує "зломи", неочікувані сценарії роботи додатку і навіть може служити доказом під час розбору інцидентів. FastAPI дозволяє легко інтегрувати модулі логування, такі як logging.
Приклад логування помилки:
import logging
logger = logging.getLogger("my_logger")
@app.get("/log-error")
async def log_error_example():
try:
x = 1 / 0 # Це явно призведе до помилки
except ZeroDivisionError as e:
logger.error(f"Помилка: {e}")
raise HTTPException(status_code=500, detail="Internal Server Error")
У логах ти побачиш, як помилка була зафіксована:
ERROR:my_logger: Помилка: division by zero
Панікувати не можна, логувати!
Коли додаток дає збій, дуже важливо не зробити ще гірше. Найчастіша помилка — це показувати користувачу занадто багато технічної інформації: відлагоджувальні повідомлення, стеки викликів і деталі "всередині". Це не тільки лякає звичайного користувача, але й може видати зайву інформацію зловмиснику.
Ось як робити не треба:
@app.get("/error")
async def bad_error():
return 1 / 0 # Ой...
У такому вигляді помилка просто вилетить назовні без будь-якої спроби її зловити або пояснити. Краще вже просто сказати, що щось пішло не так — і не видавати всю "кухню".
Практичні сценарії обробки помилок
Іноді простого коду raise HTTPException недостатньо — треба подумати і про те, як помилка виглядатиме для користувача. Нижче — кілька життєвих ситуацій.
Повідомлення про помилку у вигляді сторінки
Іноді користувач очікує не JSON-відповідь, а повністю кастомізовану сторінку помилки. Наприклад, для помилки 404 ми можемо повернути HTML-сторінку.
from fastapi.responses import HTMLResponse
@app.get("/custom-404", response_class=HTMLResponse)
async def custom_not_found():
raise HTTPException(
status_code=404,
detail="<h1>Упс! Сторінку не знайдено</h1><p>Схоже, ви зайшли не туди.</p>",
)
Відвідувач побачить оптимістичне повідомлення, а не грубий текст помилки.
Повідомлення з деталями для розробників
Зазвичай розробники тестують API за допомогою інструментів типу Swagger або Postman. У таких випадках корисно, якщо система може видавати розширені дані для налагодження, але тільки за певних умов (наприклад, у режимі розробки):
DEBUG_MODE = True
@app.get("/debug-error")
async def debug_error():
try:
1 / 0
except ZeroDivisionError as e:
if DEBUG_MODE:
raise HTTPException(status_code=500, detail=f"Помилка: {e}")
else:
raise HTTPException(status_code=500, detail="Internal Server Error")
У режимі DEBUG_MODE=True ми бачимо точну інформацію, але в продакшені такі деталі залишаться прихованими.
Висновок
Тепер ми розуміємо, як важливо приділяти увагу обробці помилок. У наступних лекціях розберемо більш складні теми: як обробляти стандартні HTTP-помилки (наприклад, 404 і 500), як створювати кастомні обробники, власні виключення, а також як логувати помилки і діагностувати їх за допомогою middleware. Запасайся терпінням — попереду глибоке занурення!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ