uv — современный менеджер пакетов Python

10 сентября 2026
Автор

Антон Ларичев

uv — это инструмент для управления пакетами и проектами на Python, написанный на Rust командой Astral (авторы Ruff). Он в десятки раз быстрее pip, заменяет сразу несколько утилит и предлагает единый интерфейс для всего цикла работы с проектом.

Зачем нужен uv

До uv типичный Python-проект требовал нескольких инструментов:

  • virtualenv или venv — создание виртуальных окружений
  • pip — установка пакетов
  • pip-tools — компиляция lockfile из требований
  • pyenv — управление версиями Python
  • Poetry или PDM — управление зависимостями проекта

uv объединяет всё это в один бинарный файл. При этом он совместим со стандартом pyproject.toml и форматом requirements.txt, поэтому его можно внедрять постепенно.

Курс по теме

Курс Python с нуля

40 000+ студентов · рейтинг 4.8 · гарантия возврата 30 дней

Установка

На macOS и Linux:

curl -LsSf https://astral.sh/uv/install.sh | sh

На Windows (PowerShell):

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Через pip (если уже есть Python):

pip install uv

Проверка установки:

uv --version
# uv 0.5.x (..)

uv — это единственный бинарный файл без зависимостей. Обновление выполняется командой uv self update.

Управление версиями Python

uv умеет скачивать и переключать версии Python без pyenv:

# Посмотреть доступные версии
uv python list

# Установить конкретную версию
uv python install 3.12
uv python install 3.11 3.13

# Использовать конкретную версию в текущем проекте
uv python pin 3.12

Команда uv python pin создаёт файл .python-version в корне проекта. uv автоматически использует версию из этого файла.

Инициализация проекта

Создание нового проекта:

uv init my-project
cd my-project

Это создаст структуру:

my-project/
├── pyproject.toml
├── README.md
├── .python-version
└── src/
    └── my_project/
        └── __init__.py

Файл pyproject.toml будет выглядеть так:

[project]
name = "my-project"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []

Для скриптов без пакетной структуры удобен флаг --script:

uv init --script script.py

Виртуальные окружения

Создание окружения вручную:

# Создать окружение в .venv
uv venv

# С конкретной версией Python
uv venv --python 3.11

# С пользовательским именем
uv venv my-env

Активация стандартная:

# Linux / macOS
source .venv/bin/activate

# Windows
.venv\Scripts\activate

Однако при использовании проектных команд uv run активировать окружение вручную не нужно — uv управляет им автоматически.

Управление зависимостями

Добавление пакетов

# Добавить зависимость в pyproject.toml и установить
uv add requests
uv add "fastapi>=0.100"
uv add "pydantic[email]"

# Добавить зависимость только для разработки
uv add --dev pytest ruff mypy

# Добавить зависимость для конкретной группы
uv add --group lint ruff

После выполнения uv add в pyproject.toml появится запись:

[project]
dependencies = [
    "requests>=2.32",
    "fastapi>=0.100",
    "pydantic[email]>=2.0",
]

[dependency-groups]
dev = [
    "pytest>=8.0",
    "ruff>=0.8",
    "mypy>=1.0",
]

Удаление пакетов

uv remove requests
uv remove --dev pytest

Установка зависимостей

# Установить все зависимости из pyproject.toml
uv sync

# Без dev-зависимостей (для продакшена)
uv sync --no-dev

# Только конкретные группы
uv sync --group lint

Lockfile

uv автоматически создаёт и обновляет файл uv.lock при каждом uv add, uv remove и uv sync. Этот файл фиксирует точные версии всех пакетов и их транзитивных зависимостей.

Фрагмент uv.lock:

version = 1
requires-python = ">=3.12"

[[package]]
name = "requests"
version = "2.32.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
    { name = "certifi" },
    { name = "charset-normalizer" },
    { name = "idna" },
    { name = "urllib3" },
]

Файл uv.lock нужно коммитить в репозиторий — это гарантирует воспроизводимые сборки в CI и на машинах других разработчиков.

Обновление зависимостей:

# Обновить все пакеты
uv lock --upgrade

# Обновить конкретный пакет
uv lock --upgrade-package requests

Запуск команд с uv run

uv run запускает команды внутри виртуального окружения проекта, не требуя его активации:

# Запустить скрипт
uv run python main.py

# Запустить тесты
uv run pytest

# Запустить любую установленную утилиту
uv run ruff check .
uv run mypy src/

Это особенно удобно в Makefile или CI-скриптах, где управлять активацией окружения неудобно.

Работа с pip-совместимым интерфейсом

Если нужно использовать uv как замену pip без pyproject.toml:

# Установить пакет
uv pip install requests

# Установить из requirements.txt
uv pip install -r requirements.txt

# Заморозить текущие зависимости
uv pip freeze > requirements.txt

# Показать установленные пакеты
uv pip list

# Удалить пакет
uv pip uninstall requests

Такой режим удобен для постепенного перехода с pip без перестройки проекта.

Компиляция requirements

uv умеет компилировать requirements.txt с зафиксированными версиями из requirements.in (замена pip-tools):

# requirements.in
requests
fastapi>=0.100
# Скомпилировать с разрешёнными версиями
uv pip compile requirements.in -o requirements.txt

Результат:

# This file was autogenerated by uv
anyio==4.7.0
    # via starlette
certifi==2024.12.14
    # via requests
fastapi==0.115.6
requests==2.32.3
...

Скрипты с встроенными зависимостями

uv поддерживает стандарт PEP 723 — зависимости прямо в скрипте:

# /// script
# requires-python = ">=3.11"
# dependencies = [
#   "requests",
#   "rich",
# ]
# ///

import requests
from rich.console import Console

console = Console()
response = requests.get("https://api.github.com/repos/astral-sh/uv")
data = response.json()
console.print(f"Stars: [bold]{data['stargazers_count']}[/bold]")

Запуск скрипта — uv сам создаст изолированное окружение с нужными пакетами:

uv run script.py

Это удобно для одноразовых утилит, которые не стоит включать в проект.

Установка глобальных утилит

uv заменяет pipx для установки CLI-инструментов:

# Установить инструмент глобально
uv tool install ruff
uv tool install httpie
uv tool install black

# Запустить инструмент без установки
uv tool run ruff check .

# Короткий псевдоним для uvx
uvx ruff check .

# Обновить все инструменты
uv tool upgrade --all

# Список установленных инструментов
uv tool list

Каждый инструмент устанавливается в изолированное окружение, поэтому конфликты зависимостей исключены.

Практический пример: FastAPI-проект

Создадим API-проект с нуля:

uv init fastapi-demo
cd fastapi-demo
uv python pin 3.12

# Добавить основные зависимости
uv add fastapi uvicorn[standard]

# Добавить dev-зависимости
uv add --dev pytest httpx ruff mypy

Файл src/fastapi_demo/main.py:

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root() -> dict[str, str]:
    return {"message": "Hello from uv-managed project"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None) -> dict:
    return {"item_id": item_id, "q": q}

Файл tests/test_main.py:

from fastapi.testclient import TestClient
from fastapi_demo.main import app

client = TestClient(app)


def test_read_root():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"message": "Hello from uv-managed project"}


def test_read_item():
    response = client.get("/items/42?q=test")
    assert response.status_code == 200
    data = response.json()
    assert data["item_id"] == 42
    assert data["q"] == "test"

Запуск сервера и тестов:

# Запуск сервера разработки
uv run uvicorn fastapi_demo.main:app --reload

# Запуск тестов
uv run pytest

# Линтинг
uv run ruff check .

# Проверка типов
uv run mypy src/

Конфигурация в pyproject.toml

uv читает настройки из секции [tool.uv]:

[tool.uv]
# Зеркало PyPI для корпоративных сред
index-url = "https://pypi.company.com/simple"

# Дополнительные индексы
extra-index-url = ["https://pypi.org/simple"]

# Ограничения для всего дерева зависимостей
constraint-dependencies = [
    "urllib3<2",
]

# Пакеты, которые не нужно обновлять
override-dependencies = [
    "numpy==1.26.4",
]

Сравнение с другими инструментами

Задача pip Poetry uv
Установка пакетов pip install poetry add uv add
Виртуальные окружения python -m venv встроено uv venv
Lockfile pip-tools poetry.lock uv.lock
Версии Python pyenv встроено uv python
Глобальные утилиты pipx нет uv tool
Скорость базовая медленная в 10-100 раз быстрее

uv при первой установке пакета скачивает его, а при повторной — берёт из глобального кеша. Для больших проектов с CI это экономит минуты.

Использование в CI/CD

Пример для GitHub Actions:

name: CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v4
        with:
          enable-cache: true

      - name: Set up Python
        run: uv python install

      - name: Install dependencies
        run: uv sync --frozen

      - name: Run tests
        run: uv run pytest

      - name: Run linter
        run: uv run ruff check .

Флаг --frozen запрещает изменение lockfile во время синхронизации — если uv.lock не соответствует pyproject.toml, команда завершится с ошибкой. Это защищает CI от неожиданных обновлений.

Dockerfile с uv

FROM python:3.12-slim

COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv

WORKDIR /app

COPY pyproject.toml uv.lock ./

# Установить только продакшен-зависимости
RUN uv sync --frozen --no-dev

COPY src/ src/

CMD ["uv", "run", "uvicorn", "my_app.main:app", "--host", "0.0.0.0"]

Кеширование слоёв работает правильно: зависимости переустанавливаются только при изменении pyproject.toml или uv.lock.

Итог

uv охватывает весь цикл работы с Python-проектом: установку интерпретатора, создание окружений, управление зависимостями, компиляцию lockfile и запуск инструментов. Скорость работы значительно выше pip и Poetry за счёт реализации на Rust и агрессивного кеширования. Совместимость с pyproject.toml и requirements.txt позволяет внедрять uv в существующие проекты без полного переписывания инфраструктуры.

Освоить Python с нуля и научиться правильно организовывать проекты можно на курсе Python для разработчиков на PurpleSchool.

Python subprocess: запуск внешних команд и процессовСтрелочка вправо

Постройте личный план изучения Python до уровня Middle — бесплатно!

Python — часть карты развития Backend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Все гайды по Python

Как отправлять запросы с помощью requests в PythonПочему Python выводит значение без команды printКак работает команда print в PythonВозможности Python для автоматизации задачРабота с JSON в Python на примерахPython get — методы получения данныхКак находить и исправлять ошибки в PythonРабота с данными через API и внешние сервисыСтруктура и оформление кода PythonОсновы Django с PythonПолезные приёмы в Python для повседневной работыИспользование locals в Python для отладкиИнтеграция PHP и PythonКак выполнять HTTPS-запросы в PythonFastAPI Python — быстрый старт: создание REST API с нуляКак работать с API в Python
Ввод целого числа в PythonВедение логов в PythonУдаление данных в Python с помощью removeОбработка исключений с помощью try/except в PythonФункция super() в Python — как вызвать метод родителяСоздание собственных контекстных менеджеров в PythonРабота с символами программирования PythonРабота с переменной X в PythonРабота с классами в PythonКак скачать Python на компьютерПростая программа на Python для начинающихОсновы Python для тех, кто начинаетЧто нового в Python 3Поддерживается ли Python 2 и стоит ли его использоватьPython 1 — с чего начиналась история языкаКоманда python print - полное руководство по выводу данныхПравила именования переменных в PythonПользовательские исключения в PythonОсновы Python coreОписание объектов PythonНаследование классов в Python — основы и примерыМножественное наследование в Python — примеры и MROКонтекстный менеджер with в Python — как работает и зачем нуженКомментарии в Python — однострочные, многострочные и docstringКакой Python выбрать для установкиКак вывести целое число с помощью print в PythonКак установить Python на Windows macOS и LinuxКак пользоваться консолью PythonКак получить последний элемент в PythonКак найти значение в PythonКак настроить PythonКак использовать print для строк в PythonКак работает интерпретатор PythonИнструкция по работе с PythonБлок finally в обработке исключений PythonЦелые числа в PythonАбстрактные классы в Python — ABC и abstractmethod
Загрузка данных PythonУправление проектами на GitHub с PythonСоздание веб-приложений на Flask PythonСоздание бота на PythonСоздание интерфейсов Python QTСоздание игр с PygameСоздание GUI в PythonКак работать со словарями в PythonРабота с библиотеками через Python PackagingРабота со временем в Python при помощи модуля timePython name — особенности переменнойМатематические операции в Python с модулем mathPython listing — что это и как использоватьPytest — тестирование на Python: полное руководствоОбработка изображений с OpenCV PythonNumPy в Python — основы и применение в задачахМашинное обучение с PythonИспользование Anaconda с PythonМодуль contextlib в Python — утилиты для контекстных менеджеровБиблиотеки Python и их применение в проектах
Возврат значений из функции в PythonВложенные функции в PythonСоздание собственных декораторов в PythonРабота с функцией map в PythonЦикл while в Python и примеры использованияОбработка чисел, введённых через input в PythonОсновные операторы в Python с примерамиУсловные выражения if else в Python для начинающихКак выполняется вызов функций call в PythonПродвинутые генераторы в Python — send, throw, close и корутиныПозиционные и именованные аргументы в PythonОбъявление переменных и управление областью видимости в PythonПередача аргументов по ссылке и по значению в PythonПередача аргументов через args и kwargs в PythonОсновные методы Python и примеры их использованияОператор match/case в Python 3.10+ — основы структурного сопоставленияПаттерны match/case в Python — деструктуризация, guard и вложенные шаблоныПрактические примеры match/case в Python — реальные сценарии примененияЛокальные и глобальные переменные в PythonЧасто используемые команды PythonКлючевые слова global и nonlocal в PythonКак создавать функции в PythonКак работает сборщик мусора в PythonКак работает область видимости переменных в PythonКак работает функция callable в PythonКак работает функция any и all в PythonКак проверить тип переменной в PythonКак передать функцию как аргумент в PythonКак использовать функцию isinstance в PythonКак использовать функцию filter в PythonКак использовать функцию filter в PythonКак использовать функцию eval безопасно в PythonКак использовать декораторы в PythonИзменяемые и неизменяемые типы данных в PythonГенераторы и yield в Python — как создавать и использоватьГенераторные выражения в Python — синтаксис и примерыФункции в Python и способы их вызоваФункции как объекты в PythonЧто такое замыкания в PythonЧто делает функция reduce в PythonЧто делает функция id в PythonАргументы по умолчанию в PythonАнонимные функции и lambda в PythonАлгоритмы на Python — примеры и объяснение
Запись данных в PythonУстановка pip в PythonУправление зависимостями requirement в PythonУправление библиотеками с помощью Python PackagingУдаление пробелов с помощью strip в PythonСтруктурирование кода в PythonСоздание исполняемого файла Python в exeРазбор traceback в модуле PythonРазбор site-packages в PythonРазбор Program Files в PythonРабота с Unicode кодировками в PythonРабота с системными функциями Python sysРабота с папкой AppData в PythonРабота с модулем logging в PythonРабота с каталогами в PythonРабота с CSV в PythonВиртуальная среда venv в Python — создание и настройкаКак создать простое приложение на PythonИспользование pip в Python для установки пакетовМодули в Python и организация кода в проектеИмпорт модулей в Python и правила подключенияРабота с файлами в Python пошаговоЧто делает компилятор Python и как он работаетПолучение строки из модуля PythonПодключение файлов в Python с includeПеременные среды в PythonСборка проекта с помощью packaging в PythonНастройка Python сервераИспользование Python на UbuntuИспользование консоли PythonИспользование кодировок в PythonИнициализация пакетов PythonИмпорт модулей PythonИмпорт имен в PythonСреда IDLE Python и базовые возможностиЧтение и запись TXT в PythonЧтение файлов в Python с помощью open file
Удаление элементов из списка PythonТипы данных в Python — обзор и рекомендацииМетоды str в Python и обработка текстаОсновные операции со строками в PythonСписки в Python и их ключевые методыСоздание списков данных в PythonРабота со строками и символами в PythonРабота со столбцами в PythonРабота со списком значений в PythonРабота с таблицами в Python с помощью DataFrameРабота с RFR в PythonРабота с пробелами в PythonРабота с массивами в PythonРабота с кортежами tuple PythonРабота с координатами X и Y в PythonРабота с ключами в PythonРабота с элементами данных PythonРабота с двоичными числами PythonРабота с данными в PythonРабота с данными NumPy PythonРабота с большими числами в PythonРабота с битами в PythonРабота с байтами в PythonЧто такое значение в Python и как его определитьМножества в Python и операции с нимиИспользование range в Python для цикловПроверка на четность в PythonПроверка числа в PythonПреобразование типов в PythonПреобразование списка в строку PythonПреобразование числа в строку в PythonПостроение графиков в PythonОпределение индекса элемента в PythonОкругление чисел в PythonОбъединение списков в Python с помощью zipМножества в PythonМассивы в Python и отличие от списковМассив чисел в PythonКак вычислить сумму чисел в PythonКортежи данных в PythonКак получить остаток от деления в PythonКак найти следующее число в PythonИспользование Unicode в PythonТип int в Python и его особенностиИндекс списка в PythonФункции для работы со строками в PythonЭлементы Python и способы доступа к нимДоступ к элементам массива в PythonДеление чисел в PythonРабота с данными в Python на практикеКак работать с числами в Python
Открыть базу знаний

Лучшие курсы по теме

Иконка молнииНовый
изображение курса

Основы Python

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Nest.js с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.6
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Docker и Ansible

Антон Ларичев
AI-тренажерыAI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий