Django-Admin.ru

Uvicorn: ASGI-сервер для FastAPI

Что такое Uvicorn и ASGI, как запустить FastAPI командой uvicorn main:app --reload, параметры host, port и workers, uvicorn.run() и Uvicorn против Gunicorn.

Редакция Django-Admin.ru
· обновлено · 11 мин чтения

Содержание · 10 разделов
  1. Что такое ASGI и зачем нужен Uvicorn
  2. Установка: uvicorn и uvicorn[standard]
  3. Запуск: uvicorn main:app —reload
  4. Параметры командной строки
  5. Запуск из кода: uvicorn.run()
  6. Uvicorn и Django
  7. Uvicorn vs Gunicorn
  8. Gunicorn с Uvicorn worker
  9. Uvicorn в Docker и Kubernetes
  10. Частые ошибки
  11. «uvicorn не является внутренней или внешней командой»
  12. Error loading ASGI app. Could not import module “main”
  13. Attribute “app” not found in module “main”
  14. Порт уже занят
  15. Изменения в коде не подхватываются
  16. Частые вопросы
  17. Как включить HTTPS в Uvicorn?
  18. Как найти и остановить процесс, который занял порт?
  19. Как отключить или настроить логи запросов?
  20. Чем можно заменить Uvicorn?
  21. Итог

Uvicorn — это ASGI-сервер для Python: он принимает HTTP- и WebSocket-соединения и передаёт запросы асинхронному приложению — FastAPI, Starlette или Django в режиме ASGI. Сам FastAPI сетевых соединений не слушает, поэтому без сервера вроде Uvicorn приложение не запустить. Быстрый ответ, как запустить FastAPI через Uvicorn:

pip install "uvicorn[standard]"
uvicorn main:app --reload

Ниже разберём, что такое ASGI, как устроена команда uvicorn main:app, какие параметры нужны в разработке и в продакшне, как запускать сервер из кода через uvicorn.run(), чем Uvicorn отличается от Gunicorn и как исправить частые ошибки запуска. Примеры проверены на Uvicorn 0.54, FastAPI 0.143 и Python 3.12.

Что такое ASGI и зачем нужен Uvicorn

Веб-приложение на Python не работает с сокетами напрямую. Между сетью и вашим кодом стоит сервер, а договорённость о том, как сервер вызывает приложение, называется интерфейсом:

  • WSGI — синхронный стандарт: один запрос занимает поток или процесс до конца обработки. Серверы: Gunicorn, uWSGI. Фреймворки: Flask, классический Django.
  • ASGI — асинхронный преемник WSGI: приложение — это корутина, и один процесс может обслуживать тысячи одновременных соединений, пока запросы ждут базу или внешний API. ASGI поддерживает WebSocket и долгие соединения. Серверы: Uvicorn, Hypercorn, Daphne. Фреймворки: FastAPI, Starlette, Django (через asgi.py).

ASGI-приложение — это асинхронная функция с тремя аргументами. Так выглядит приложение вообще без фреймворка:

# raw.py
async def app(scope, receive, send):
    assert scope["type"] == "http"
    await send({
        "type": "http.response.start",
        "status": 200,
        "headers": [(b"content-type", b"text/plain; charset=utf-8")],
    })
    await send({"type": "http.response.body", "body": "Привет от ASGI".encode()})
uvicorn raw:app
curl http://127.0.0.1:8000/
# Привет от ASGI

Uvicorn разбирает HTTP, формирует scope (метод, путь, заголовки) и вызывает app. FastAPI делает то же самое, только скрывает эту механику за декораторами @app.get() и Pydantic-моделями.

Установка: uvicorn и uvicorn[standard]

Устанавливайте сервер в виртуальное окружение проекта. Есть два варианта:

pip install uvicorn              # минимальный: чистый Python
pip install "uvicorn[standard]"  # с ускорителями и автоперезагрузкой

Набор standard добавляет uvloop (быстрый цикл событий; не устанавливается на Windows), httptools (быстрый HTTP-парсер), websockets, watchfiles (отслеживание изменений для --reload), python-dotenv (для --env-file) и pyyaml (для конфигурации логов в YAML). Кавычки вокруг "uvicorn[standard]" нужны в zsh и не мешают в других оболочках.

Если вы ставили FastAPI командой pip install "fastapi[standard]", Uvicorn со всеми ускорителями уже установлен. Пошаговая установка для Windows, macOS и Linux — в статье как установить и запустить FastAPI.

Запуск: uvicorn main:app —reload

Минимальное приложение:

# main.py
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def root():
    return {"message": "Hello, Uvicorn"}
uvicorn main:app --reload
INFO:     Will watch for changes in these directories: ['C:\\projects\\demo']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [36836] using WatchFiles
INFO:     Started server process [30672]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     127.0.0.1:62035 - "GET / HTTP/1.1" 200 OK

Запись main:app читается как «модуль main, переменная app». Если приложение лежит в пакете, путь пишется через точку: uvicorn app.main:app. Если переменная называется иначе, укажите её имя: uvicorn main:application.

Флаг --reload перезапускает сервер при изменении .py-файлов. Это режим разработки: в продакшне он не нужен, потому что тратит ресурсы на слежение за файлами.

Параметры командной строки

ПараметрПо умолчаниюНазначение
--host127.0.0.1адрес; 0.0.0.0 — принимать соединения со всех интерфейсов
--port8000порт
--reloadвыкл.автоперезагрузка при изменении кода
--reload-dirтекущая папкакакие каталоги отслеживать
--workers1число процессов; несовместим с --reload
--log-levelinfocritical, error, warning, info, debug, trace
--env-file—загрузить переменные окружения из файла
--proxy-headersвкл.доверять X-Forwarded-For и X-Forwarded-Proto от прокси
--forwarded-allow-ips127.0.0.1,::1IP прокси, заголовкам которых можно доверять
--root-path—префикс пути, если приложение опубликовано не в корне
--factoryвыкл.APP — функция, которая возвращает приложение

Полный список выводит uvicorn --help. Типичные команды:

# Разработка
uvicorn main:app --reload

# Открыть доступ из локальной сети (например, для телефона) на порту 8080
uvicorn main:app --host 0.0.0.0 --port 8080

# Продакшн на Linux-сервере: 4 процесса
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4

С --workers Uvicorn запускает родительский процесс-менеджер и указанное число процессов-воркеров; упавший воркер менеджер перезапускает. Если одновременно указать --reload и --workers, Uvicorn предупредит "workers" flag is ignored when reloading is enabled. и запустит один процесс.

Совет: в FastAPI есть собственная команда fastapi dev main.py (то же, что uvicorn main:app --reload) и fastapi run main.py (без перезагрузки, на 0.0.0.0). Внутри работает тот же Uvicorn — выбирайте то, что удобнее. Подробнее — в руководстве по FastAPI.

Запуск из кода: uvicorn.run()

Сервер можно запустить из Python-скрипта — удобно для отладки в IDE через кнопку Run:

# run.py
import uvicorn

from main import app

if __name__ == "__main__":
    uvicorn.run(app, host="127.0.0.1", port=8000)
python run.py

Для reload=True или workers приложение нужно передать строкой импорта, иначе Uvicorn не сможет загрузить его заново в новом процессе:

import uvicorn

if __name__ == "__main__":
    uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True)

Если передать объект app вместе с reload=True, сервер не запустится:

WARNING:  You must pass the application as an import string to enable 'reload' or 'workers'.

Проверка if __name__ == "__main__" обязательна: с reload или workers Uvicorn создаёт дочерние процессы, и на Windows они заново импортируют ваш скрипт — без проверки каждый из них попытается запустить сервер ещё раз.

Uvicorn и Django

Django с версии 3.0 умеет работать как ASGI-приложение: в проекте уже есть файл asgi.py. Запуск через Uvicorn:

uvicorn config.asgi:application

Здесь config — пакет проекта (тот, где лежит settings.py), application — переменная из asgi.py. Это имеет смысл, если вы используете асинхронные view или WebSocket через Django Channels; для обычного синхронного Django привычнее WSGI и Gunicorn — схема описана в статье про деплой Django на Gunicorn и Nginx.

Uvicorn vs Gunicorn

Gunicorn — WSGI-сервер и менеджер процессов, Uvicorn — ASGI-сервер, и в продакшне их часто используют вместе. Запустить FastAPI «голым» Gunicorn нельзя: стандартные воркеры Gunicorn говорят на WSGI. Зато Gunicorn умеет использовать Uvicorn как класс воркера.

КритерийUvicornGunicorn + Uvicorn worker
Протокол приложенияASGIASGI через воркер Uvicorn
Несколько процессов--workers N-w N
Перезапуск упавших воркеровестьесть
Настройка менеджера процессовбазовая: параметры командной строки--timeout, хуки, gunicorn.conf.py
Работа на Windowsданет, Gunicorn работает только на Unix
Установкаuvicorn[standard]gunicorn + uvicorn-worker

Раньше документация FastAPI рекомендовала связку Gunicorn + Uvicorn, потому что Uvicorn не умел управлять процессами. Теперь у uvicorn --workers есть свой менеджер процессов, и документация FastAPI для запуска нескольких воркеров показывает fastapi run --workers 4 или uvicorn --workers 4. Gunicorn остаётся разумным выбором, если команда уже привыкла к его настройкам или нужны его хуки и таймауты.

Gunicorn с Uvicorn worker

Класс воркера uvicorn.workers.UvicornWorker объявлен устаревшим: при импорте он выдаёт DeprecationWarning с советом перейти на пакет uvicorn-worker. Актуальный вариант:

pip install gunicorn uvicorn-worker
gunicorn main:app --workers 4 --worker-class uvicorn_worker.UvicornWorker --bind 0.0.0.0:8000

Сокращённо — -w 4 -k uvicorn_worker.UvicornWorker -b 0.0.0.0:8000. Количество воркеров обычно подбирают от числа ядер процессора; для асинхронного приложения часто хватает одного воркера на ядро.

Uvicorn в Docker и Kubernetes

Если оркестратор сам запускает несколько копий контейнера (Kubernetes, Docker Swarm), внутри контейнера обычно достаточно одного процесса Uvicorn без --workers: масштабированием занимается кластер. В одиночном контейнере или на обычном сервере используйте --workers. Перед приложением в продакшне ставят обратный прокси (Nginx, Traefik), который отвечает за HTTPS; чтобы Uvicorn видел реальный IP клиента, укажите адрес прокси в --forwarded-allow-ips.

Частые ошибки

«uvicorn не является внутренней или внешней командой»

В Windows это выглядит так: 'uvicorn' не является внутренней или внешней командой, исполняемой программой или пакетным файлом; в PowerShell — Имя "uvicorn" не распознано как имя командлета; в Linux с bash — uvicorn: command not found, в macOS с zsh — zsh: command not found: uvicorn. Причина одна: исполняемый файл uvicorn не найден в PATH. Обычно не активировано виртуальное окружение или Uvicorn установлен в другой интерпретатор.

Самый надёжный способ — запускать через интерпретатор:

python -m uvicorn main:app --reload    # Windows
python3 -m uvicorn main:app --reload   # macOS / Linux

Если и это даёт No module named uvicorn, пакет не установлен в текущее окружение: выполните python -m pip install "uvicorn[standard]".

Error loading ASGI app. Could not import module “main”

ERROR:    Error loading ASGI app. Could not import module "mian".

Опечатка в имени модуля или команда запущена не из той папки. Перейдите в каталог, где лежит main.py, или укажите его через --app-dir.

Attribute “app” not found in module “main”

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

После двоеточия указано имя переменной, которой нет в модуле. Проверьте, как называется объект FastAPI() в коде.

Порт уже занят

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

Так ошибка выглядит в Windows. В Linux вместо 10048 будет [Errno 98] и текст address already in use, в macOS — [Errno 48] с тем же текстом. На этом порту уже работает другой процесс — часто предыдущий запуск Uvicorn. Остановите его или запустите сервер на другом порту: --port 8001.

Изменения в коде не подхватываются

Сервер запущен без --reload или с --workers. В разработке используйте uvicorn main:app --reload или fastapi dev.

Частые вопросы

Как включить HTTPS в Uvicorn?

Передайте ключ и сертификат:

uvicorn main:app --host 0.0.0.0 --port 8443 --ssl-keyfile key.pem --ssl-certfile cert.pem

Так удобно проверить HTTPS локально, например с сертификатом от mkcert. В продакшне сертификаты обычно обслуживает обратный прокси (Nginx, Traefik, Caddy): он сам продлевает сертификаты Let’s Encrypt, а Uvicorn за ним работает по обычному HTTP.

Как найти и остановить процесс, который занял порт?

Сначала узнайте PID процесса, затем завершите его:

# Windows
netstat -ano | findstr :8000
taskkill /PID 12345 /F
# Linux / macOS
lsof -i :8000
kill 12345

Вместо 12345 подставьте PID из вывода первой команды. Сервер, запущенный в своём терминале, останавливают сочетанием Ctrl+C.

Как отключить или настроить логи запросов?

Строки вида "GET / HTTP/1.1" 200 OK — это access log. Отключить его можно флагом --no-access-log, а уровень подробности остальных сообщений меняет --log-level warning. Для своего формата и вывода в файл передайте конфигурацию модуля logging в файле JSON, YAML или INI: --log-config logging.yaml (для YAML нужен pyyaml, он входит в uvicorn[standard]).

Чем можно заменить Uvicorn?

Самые известные ASGI-серверы помимо Uvicorn: Hypercorn — поддерживает HTTP/2 и HTTP/3, Granian — сервер на Rust, который запускает ASGI- и WSGI-приложения, и Daphne — сервер проекта Django Channels. FastAPI работает с любым из них, но команды fastapi dev и fastapi run используют Uvicorn. Если у вас нет конкретной причины (например, нужен HTTP/2 без прокси), оставайтесь на Uvicorn.

Итог

Uvicorn — ASGI-сервер, который запускает FastAPI и другие асинхронные приложения. В разработке хватает команды uvicorn main:app --reload, в продакшне — --host 0.0.0.0, --workers и обратного прокси перед сервером. Gunicorn с воркером uvicorn_worker.UvicornWorker пригодится, если нужны его настройки, но работает он только на Unix.

Дальше — основы фреймворка в руководстве по FastAPI, подключение базы данных в статье FastAPI и SQLAlchemy и защита эндпоинтов в материале про авторизацию через JWT. Полный список настроек — в документации Uvicorn.

  • #Uvicorn
  • #FastAPI
  • #ASGI
  • #Gunicorn
  • #Деплой
↑ ↓ выборEnter открытьEsc закрыть