# FastAPI с нуля: установка, app = FastAPI(), первый маршрут и запуск сервера<no value>

## Что мы изучим?

Этот урок — **полная настройка с нуля** настоящего сервера:

1. **Виртуальное окружение** (venv): куда устанавливаются библиотеки.
2. **Установка FastAPI** через `pip`.
3. **`main.py`**: импорт, создание `app` и первый **маршрут** (Route).
4. **Запуск** через `uvicorn`.
5. **Проверка**: браузер, curl и автоматическая страница документации `/docs`.

## Зачем это нужно?

В теме сетей мы видели, что включает «ручной» сервер: `bind`, `listen`, `accept` и разбор текста. Это много работы, и легко упасть на плохом вводе. **FastAPI** делает всё это за нас: принимает запрос, разбирает HTTP, находит нужную функцию, превращает ответ в JSON и проверяет типы. Мы пишем **только логику**.

FastAPI — одна из самых распространённых библиотек для бэкенда на Python, особенно для API и в мире данных и AI.

## Объяснение с основ

### Что такое FastAPI?

**FastAPI** — **фреймворк** (Framework) для построения Web API на Python. Фреймворк = библиотека, которая диктует **структуру**: «вы пишете функции, а я вызываю их, когда приходит подходящий запрос».

**Uvicorn** — это **сам HTTP-сервер**: программа, которая слушает порт (тема сетей: `listen`), принимает соединения и передаёт каждый запрос в FastAPI. FastAPI = **что** ответить. Uvicorn = **приёмная** на входе.

```text
Browser ──HTTP──► Uvicorn (listens on port 8000) ──► FastAPI (finds the right function) ──► your function
        ◄──JSON── Uvicorn ◄── FastAPI (converts dict to JSON) ◄──────────────────────── return {...}
```

### Внешняя библиотека и pip

До сих пор мы использовали только модули, **которые поставляются с Python** (`os`, `json`, `logging`). FastAPI — **внешняя библиотека** (Third-party Package), поэтому её нужно установить.

**pip** — менеджер пакетов Python: он скачивает библиотеки из **PyPI** (публичного хранилища библиотек Python) и устанавливает их.

### Виртуальное окружение (venv) — и зачем оно нужно

Если устанавливать библиотеки «глобально» (для всего компьютера), одному проекту нужна FastAPI версии 0.100, другому — 0.142, и возникает конфликт. **Виртуальное окружение** (Virtual Environment, venv) = **личная папка проекта** со своей копией Python и своих библиотек. У каждого проекта свои библиотеки, без конфликтов.

{{< box "analogy" "Аналогия: ящик с инструментами для каждого проекта" >}}
Мастер, который работает в трёх домах, не держит все инструменты в одной куче дома. На каждом объекте **свой ящик с инструментами** — ровно с тем, что нужно объекту. venv = ящик с инструментами проекта. А его «активация» (activate) = «сейчас я работаю с **этим** ящиком».
{{< /box >}}

### Декоратор — `@app.get("/")`

Строка, начинающаяся с `@` над `def`, — это **декоратор** (Decorator; мы видели `@property` в теме ООП). В FastAPI `@app.get("/")` говорит: **«зарегистрируй функцию ниже как обработчик запросов `GET` к пути `/`»**.

Помните калькулятор со словарём функций (`OPERATIONS = {"+": add, ...}`)? FastAPI строит ровно такую таблицу: **(метод, путь) → функция**. Каждый `@app.get(...)` добавляет строку в таблицу. Когда приходит запрос, FastAPI ищет его в таблице и вызывает функцию. (Это функции как объекты в действии!)

**Маршрут** (Route) = связь между Endpoint-ом (метод + путь) и функцией, которая его обрабатывает.

## Синтаксис

### Шаг 1 — папка и виртуальное окружение

```powershell
mkdir ~\dev\kodkod6\week-4\hello-api
cd ~\dev\kodkod6\week-4\hello-api
python -m venv .venv
```

### Шаг 2 — активация окружения

**Windows (PowerShell):**

```powershell
.venv\Scripts\Activate.ps1
```

**Mac / Linux:**

```bash
source .venv/bin/activate
```

Приглашение (Prompt) меняется и начинается с `(.venv)`. **Отныне `python` и `pip` принадлежат проекту.**

### Шаг 3 — установка

```powershell
pip install "fastapi[standard]"
```

`[standard]` устанавливает FastAPI **вместе с** Uvicorn и ещё несколькими полезными инструментами. Проверка:

```powershell
pip list
```

### Шаг 4 — `main.py`

```python
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def home():
    return {"message": "Hello from my first server!"}
```

### Шаг 5 — запуск

```powershell
uvicorn main:app --reload
```

### Шаг 6 — проверка

- Браузер: `http://127.0.0.1:8000/`
- Документация: `http://127.0.0.1:8000/docs`
- Остановка: `Ctrl + C`

## Первый пример кода

После шагов 1–5 терминал показывает:

```text
INFO:     Will watch for changes in these directories: ['C:\\Users\\dana\\dev\\kodkod6\\week-4\\hello-api']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [43864] using StatReload
INFO:     Started server process [29224]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
```

В браузере, `http://127.0.0.1:8000/`:

```json
{"message":"Hello from my first server!"}
```

А в терминале добавляется строка о запросе:

```text
INFO:     127.0.0.1:52311 - "GET / HTTP/1.1" 200 OK
```

## Разбор кода построчно

**`main.py`:**

| Строка | Объяснение |
|---|---|
| `from fastapi import FastAPI` | Импортирует **класс** с именем `FastAPI` из библиотеки (урок о модулях: `from ... import`). |
| `app = FastAPI()` | Создаёт **объект** этого класса (тема ООП!). `app` — **приложение**: оно хранит таблицу маршрутов, и с ним будет общаться Uvicorn. |
| `@app.get("/")` | Декоратор: «зарегистрируй `home` как обработчик `GET /`». `get` — **метод** объекта `app`. |
| `def home():` | Обычная функция. Имя произвольное. FastAPI узнаёт её по декоратору, а не по имени. |
| `return {"message": "..."}` | Вы возвращаете **dict**, а FastAPI автоматически превращает его в **JSON** (сериализация, урок о JSON) и возвращает код 200. |

**Команда `uvicorn main:app --reload`:**

| Часть | Объяснение |
|---|---|
| `uvicorn` | Запуск HTTP-сервера. |
| `main` | **Модуль**: файл `main.py` (без `.py`). |
| `:app` | **Объект** внутри модуля: переменная `app`. «Запусти приложение с именем `app`, которое находится в `main`». |
| `--reload` | **Режим разработки**: когда вы сохраняете изменение в коде, сервер сам автоматически перезапускается. **Только для разработки**, не на настоящем сервере. |

**Строки вывода:**

| Строка | Значение (и связь с темой сетей) |
|---|---|
| `Will watch for changes...` | Режим `--reload`: наблюдение за файлами в папке. |
| `Uvicorn running on http://127.0.0.1:8000` | Сервер **слушает** (`listen`) на **localhost**, **порт 8000**. |
| `Started reloader process [43864]` | Процесс-«наблюдатель», который обнаруживает изменения. **PID**. |
| `Started server process [29224]` | **Процесс**, который действительно обрабатывает запросы. Ещё один PID. |
| `"GET / HTTP/1.1" 200 OK` | **Лог** каждого запроса: метод, путь, версия и код состояния. |

## Ещё один пример

**Больше маршрутов и `/docs`.** Обновите `main.py` (с `--reload` сервер обновится сам в момент сохранения):

```python
from fastapi import FastAPI

app = FastAPI(title="Kodkod Hello API")

COURSE = {"name": "Kodkod 6", "weeks": 5, "topics": ["OS", "Python", "OOP", "Backend", "DB"]}

@app.get("/")
def home():
    return {"message": "Hello from my first server!"}

@app.get("/course")
def course_info():
    return COURSE

@app.get("/course/topics")
def course_topics():
    return COURSE["topics"]

@app.get("/health")
def health():
    return {"status": "ok"}
```

**Проверка через curl** (в **другом** терминале, потому что первый занят сервером):

```powershell
curl.exe http://127.0.0.1:8000/course
curl.exe http://127.0.0.1:8000/course/topics
curl.exe -i http://127.0.0.1:8000/nothing
```

**Вывод:**

```text
{"name":"Kodkod 6","weeks":5,"topics":["OS","Python","OOP","Backend","DB"]}
["OS","Python","OOP","Backend","DB"]
HTTP/1.1 404 Not Found
date: Tue, 06 Oct 2026 14:30:00 GMT
server: uvicorn
content-length: 22
content-type: application/json

{"detail":"Not Found"}
```

**Разбор:**

- `FastAPI(title="Kodkod Hello API")` — имя приложения, которое появится на странице документации.
- **Можно возвращать всё, что умеет представить JSON**: dict (`/course`), **список** (`/course/topics`), строку или число.
- **Путь, который не определён** (`/nothing`): FastAPI сам возвращает **404** с JSON ошибки. Мы не написали для этого ни строки.
- `/health` — Endpoint, распространённый на настоящих серверах: системы мониторинга проверяют его каждые несколько секунд, чтобы знать, что сервер жив.

### `/docs` — автоматическая документация

Откройте `http://127.0.0.1:8000/docs`. FastAPI **сам построил** интерактивную страницу документации (она называется **Swagger UI**):

- Список **всех Endpoint-ов** с методом и путём.
- Щелчок по Endpoint-у → **Try it out** → **Execute**: отправляет настоящий запрос и показывает ответ.
- Документация автоматически обновляется с каждым новым маршрутом.

В теме API студентов мы будем использовать её как **главный инструмент проверки** сервера.

## Типичная ошибка

**Ошибка 1: установка без активации venv** или открытие нового терминала с забытой активацией.

```text
uvicorn : The term 'uvicorn' is not recognized ...
```

Или:

```text
ModuleNotFoundError: No module named 'fastapi'
```

**Проверка:** начинается ли приглашение с `(.venv)`? Если нет — `.venv\Scripts\Activate.ps1`. **В каждом новом терминале активируйте снова.** (Альтернатива, которая работает всегда: `python -m uvicorn main:app --reload`.)

**Ошибка 2: в Windows активация заблокирована.**

```text
.venv\Scripts\Activate.ps1 cannot be loaded because running scripts is disabled on this system.
```

PowerShell по умолчанию блокирует запуск скриптов. Откройте PowerShell и выполните **один раз**:

```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```

(Это разрешает локальные скрипты только для вашего пользователя. Вспомните права из темы операционной системы!)

**Ошибка 3: `main:app` не соответствует коду.**

```text
ERROR:    Error loading ASGI app. Attribute "app" not found in module "main".
```

Файл называется не `main.py`, или переменная называется не `app` (например, `application = FastAPI()`). Формат всегда `<file>:<variable>`. И запускают **из папки, где лежит файл** (текущая папка, Current Working Directory, — вспомните тему операционной системы!).

**Ошибка 4: занятый порт.**

```text
ERROR:    [WinError 10048] error while attempting to bind on address ('127.0.0.1', 8000): only one usage of each socket address (protocol/network address/port) is normally permitted
```

Другой сервер (или предыдущая копия того же сервера) уже слушает 8000 (вспомните порты из темы сетей!). Остановите его через `Ctrl + C` в его терминале или запустите на другом порту: `uvicorn main:app --reload --port 8001`.

**Ошибка 5: добавить `.venv` в Git.** Папка огромная, в ней тысячи файлов, которые зависят от вашего компьютера. Добавьте в `.gitignore`:

```text
.venv/
__pycache__/
```

А вместо этого сохраните **список** библиотек: `pip freeze > requirements.txt`. Тот, кто скачает проект, выполнит `pip install -r requirements.txt`.

<!-- exercises:start — generated by scripts/intro6/sync_site_exercises.py; edit scripts/intro6/exercises/ -->
## Практика

Упражнения опираются только на то, что пройдено в этом уроке и в предыдущих. Сначала попробуйте сами, и только потом открывайте решение.

### Упражнение 1: Настройка проекта

Напишите последовательность команд, которая настраивает проект `hello-api`: папку, виртуальное окружение, его активацию (Windows) и установку FastAPI. Какова роль виртуального окружения?

{{< solution >}}
```powershell
mkdir hello-api
cd hello-api
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install "fastapi[standard]"
pip list
```

(На Mac: `source .venv/bin/activate`.)

**Виртуальное окружение (venv)** изолирует пакеты проекта: у каждого проекта свои версии, без конфликтов с другими проектами или с Python компьютера. Папка `.venv` не попадает в Git.
{{< /solution >}}

### Упражнение 2: Первый маршрут

Напишите `main.py` с приложением FastAPI и маршрутом (Route) для `/`, который возвращает `{"message": "Hello from my first server!"}`. Как его запустить и на какой адрес зайти?

{{< solution >}}
```python
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def home():
    return {"message": "Hello from my first server!"}
```

Запуск:

```powershell
uvicorn main:app --reload
```

И откройте `http://127.0.0.1:8000`. `main:app` = файл `main.py`, переменная `app`. `--reload` перезапускает сервер после каждого сохранения.
{{< /solution >}}

### Упражнение 3: От запроса к функции

Расставьте по порядку путь запроса от браузера до нашей функции и обратно:

- (а) FastAPI превращает dict в JSON
- (б) Браузер отправляет `GET /`
- (в) Функция `home()` возвращает dict
- (г) Uvicorn получает запрос на порту 8000
- (д) FastAPI находит функцию, которая соответствует `GET /`

{{< solution >}}
Порядок: **(б), (г), (д), (в), (а)**

1. Браузер отправляет `GET /`.
2. **Uvicorn** — сам сервер — получает запрос на порту 8000.
3. **FastAPI** находит маршрут, который соответствует методу и пути.
4. Наша функция возвращает обычный **dict**.
5. FastAPI превращает его в **JSON** и возвращает ответ с кодом 200.
{{< /solution >}}

### Упражнение 4: API цитат

Напишите API цитат со списком цитат (словари с `text` и `author`) и двумя маршрутами:

- `GET /quotes` — все цитаты;
- `GET /quotes/count` — `{"count": <number>}`.

Дайте приложению заголовок `"Quotes API"`.

{{< solution >}}
```python
from fastapi import FastAPI

app = FastAPI(title="Quotes API")

QUOTES = [
    {"text": "Simple is better than complex.", "author": "The Zen of Python"},
    {"text": "Readability counts.", "author": "The Zen of Python"},
    {"text": "Talk is cheap. Show me the code.", "author": "Linus Torvalds"},
]


@app.get("/quotes")
def all_quotes():
    return QUOTES


@app.get("/quotes/count")
def count_quotes():
    return {"count": len(QUOTES)}
```

`GET /quotes/count` возвращает `{"count": 3}`. FastAPI превращает в JSON и список. Заголовок появляется на странице документации по адресу `/docs`.
{{< /solution >}}

### Упражнение 5: Swagger UI

1. Что находится по адресу `http://127.0.0.1:8000/docs`?
2. Как с его помощью проверить маршрут?

{{< solution >}}
1. **Swagger UI** — страница документации, которую FastAPI строит **автоматически** по коду: все маршруты, метод каждого, параметры и ответы.
2. Откройте маршрут, нажмите **Try it out**, заполните параметры, если они есть, и нажмите **Execute**. Вы увидите отправленный запрос, код состояния и тело ответа — без написания клиента.
{{< /solution >}}

<!-- exercises:end -->

## Итоги

- **FastAPI** = фреймворк, в котором определяют маршруты. **Uvicorn** = HTTP-сервер, который слушает порт и передаёт запросы в FastAPI.
- **venv**: `python -m venv .venv`, активация (`Activate.ps1` / `source .venv/bin/activate`), а затем `pip install "fastapi[standard]"`. В каждом новом терминале активируйте снова.
- `app = FastAPI()` = объект приложения. **`@app.get("/path")`** регистрирует функцию как обработчик `GET /path`.
- Возвращайте dict или список, и FastAPI превратит их в JSON с кодом 200. Несуществующий путь автоматически получает 404.
- Запуск: **`uvicorn main:app --reload`** (`file:variable`) из папки файла. Остановка: `Ctrl + C`.
- **`/docs`** = интерактивная автоматическая документация и проверка.
- `.venv/` — в `.gitignore`. `requirements.txt` — в Git.

<!-- docs:start — generated by scripts/intro6/site_docs.py; edit the links there -->

## Официальная документация

- [FastAPI — Virtual Environments](https://fastapi.tiangolo.com/virtual-environments/)
- [FastAPI — First Steps](https://fastapi.tiangolo.com/tutorial/first-steps/)
- [FastAPI — Interactive API docs](https://fastapi.tiangolo.com/tutorial/first-steps/#interactive-api-docs)

<!-- docs:end -->
