uv объединяет управление версиями Python, виртуальными окружениями и зависимостями. Но у него есть два разных интерфейса, которые легко перепутать:
uv add,uv remove,uv runиuv syncуправляют проектом черезpyproject.tomlиuv.lock;uv pipработает напрямую с виртуальным окружением и нужен прежде всего для совместимости с привычными командамиpip.
Для нового проекта почти всегда выбирай первый вариант. Минимальный рабочий цикл выглядит так:
uv init --no-package weather-bot
cd weather-bot
uv add requests
uv run python -c "import requests; print(requests.__version__)"
Отдельно создавать и активировать окружение не пришлось: uv подготовил .venv, записал зависимость в проект и запустил нужный интерпретатор.
Что заменяет uv
uv не меняет сам язык Python. Он берёт на себя операции, для которых раньше требовались отдельные команды или инструменты.
| Задача | pip и venv | Проект uv |
|---|---|---|
| Создать проект | создать каталог и файлы вручную | uv init |
| Создать окружение | python -m venv .venv | создаётся при первой проектной команде |
| Добавить пакет | python -m pip install requests | uv add requests |
| Зафиксировать версии | pip freeze > requirements.txt | uv обновляет uv.lock |
| Запустить команду | активировать .venv, затем запустить | uv run ... |
| Восстановить окружение | pip install -r requirements.txt | uv sync |
| Выбрать Python | установить отдельно | uv python install и uv python pin |
Это не означает, что pip и venv стали неправильными. Для небольшого учебного скрипта достаточно обычного виртуального окружения. uv полезнее, когда проект нужно одинаково запускать на нескольких компьютерах, обновлять без случайной смены всех версий и воспроизводить в CI.
Как установить uv на Windows, macOS и Linux
Актуальные способы установки перечислены в официальной документации uv.
На 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"
Если правила компании запрещают выполнять загруженный скрипт, установи uv через уже настроенный менеджер пакетов. Например, официальный вариант для PyPI:
pipx install uv
Проверь установку:
uv --version
Если терминал отвечает command not found или «имя uv не распознано», закрой его и открой снова. Установщик мог добавить каталог uv в PATH, но уже запущенная оболочка ещё не прочитала обновлённые настройки.
Как создать новый проект
Для простого приложения без сборки пакета выполни:
uv init --no-package weather-bot
cd weather-bot
uv run main.py
Флаг --no-package создаёт понятную заготовку с main.py. Начиная с uv 0.12 команда без этого флага по умолчанию готовит устанавливаемое приложение со структурой src/ и точкой входа. Для библиотеки, которую планируется импортировать или публиковать, используй отдельный шаблон:
uv init --lib weather-client
После первой команды uv run, uv add, uv sync или uv lock в проекте появятся основные служебные файлы:
pyproject.toml— метаданные и допустимые диапазоны версий прямых зависимостей;uv.lock— точные версии всех прямых и транзитивных зависимостей;.python-version— версия Python, выбранная для проекта;.venv— локальное виртуальное окружение с интерпретатором и пакетами.
В Git добавляют pyproject.toml и uv.lock. Файл .python-version тоже обычно добавляют, если команда договорилась об одной версии Python. Каталог .venv не добавляют: он зависит от операционной системы и восстанавливается командой uv sync.
uv.lock можно читать, но не нужно редактировать вручную. По документации uv это кроссплатформенный lock-файл, которым управляет сам uv.
Как добавлять, удалять и обновлять зависимости
Обычную зависимость добавляют так:
uv add requests
Команда выполняет сразу три связанных действия:
- добавляет
requestsвpyproject.toml; - пересчитывает
uv.lock; - синхронизирует
.venv.
Ограничение версии можно указать явно. Кавычки защищают символы > и < от обработки оболочкой:
uv add "requests>=2.32,<3"
Инструменты разработки лучше хранить отдельно от зависимостей приложения:
uv add --dev pytest
uv run pytest
Удаление пакета тоже должно менять описание проекта, поэтому используй:
uv remove requests
Если нужно обновить только один пакет до новейшей версии, которая подходит под ограничения проекта:
uv lock --upgrade-package requests
uv sync
Обычный uv sync не обновляет всё до последних доступных версий. При существующем uv.lock он сохраняет уже выбранные версии, пока они совместимы с pyproject.toml. Это защищает проект от случайного массового обновления.
Как запускать проект через uv run
uv run запускает команду внутри окружения проекта:
uv run python main.py
uv run pytest
uv run ruff check .
Перед запуском uv проверяет соответствие pyproject.toml, uv.lock и .venv. Поэтому активировать окружение через source .venv/bin/activate не обязательно.
Если редактору нужен готовый интерпретатор или окружение требуется восстановить заранее, запусти:
uv sync
У этой команды есть важное свойство: по умолчанию она выполняет точную синхронизацию и удаляет из .venv пакеты, которых нет в lock-файле. Поэтому пакет, установленный вручную через uv pip install, может исчезнуть после uv sync. Для постоянной зависимости проекта нужен uv add.
В CI полезно запрещать незаметное изменение lock-файла:
uv sync --locked
uv run --locked pytest
Если pyproject.toml и uv.lock расходятся, команда завершится ошибкой вместо автоматического обновления файла. Значит, разработчик забыл пересчитать и закоммитить uv.lock.
Чем uv add отличается от uv pip install
Разница не в скорости, а в том, чем управляет команда.
uv add requests
работает на уровне проекта: объявляет зависимость, обновляет lock-файл и окружение. А команда:
uv pip install requests
работает только с найденным виртуальным окружением. Она не превращает пакет в зависимость проекта и не обновляет uv.lock.
Официальная документация называет uv pip низкоуровневым интерфейсом совместимости. Он пригодится, если проект пока остаётся на requirements.txt:
uv venv
uv pip install -r requirements.txt
uv найдёт .venv в текущем или родительском каталоге даже без активации. Но внутри полноценного uv-проекта не смешивай два подхода без причины:
- нужна постоянная зависимость —
uv add; - нужно удалить её из проекта —
uv remove; - нужно восстановить состояние из lock-файла —
uv sync; - нужно временно проверить пакет или сохранить старый процесс на requirements —
uv pip.
Несмотря на название, uv pip не запускает установленный pip. Он повторяет распространённые команды и поведение pip, но полная совместимость не гарантируется.
Как перенести существующий проект с requirements.txt
Сначала сохрани рабочее состояние проекта и не удаляй requirements.txt: он понадобится для сравнения и отката.
Если pyproject.toml ещё нет, создай только его, не добавляя в существующий репозиторий README, исходники и новый каталог Git:
uv init --bare
Если pyproject.toml уже существует, этот шаг пропусти.
Дальше выбор зависит от того, как устроены старые файлы.
В requirements.txt перечислены только прямые зависимости
Например, файл написан вручную и содержит django, psycopg и gunicorn, а не полный вывод pip freeze. Его можно импортировать напрямую:
uv add -r requirements.txt
uv run python main.py
После проверки тестов добавь в Git pyproject.toml и uv.lock.
Есть requirements.in и зафиксированный requirements.txt
Если прямые зависимости хранятся в requirements.in, а requirements.txt содержит их точные разрешённые версии, используй старый lock как ограничения:
uv add -r requirements.in -c requirements.txt
Такой способ рекомендует официальное руководство по переходу с pip: прямые зависимости попадут в pyproject.toml, а версии при первой сборке uv.lock останутся прежними, если набор ограничений совместим.
requirements.txt получен командой pip freeze
uv add -r requirements.txt технически сработает, но объявит прямыми все строки, включая транзитивные пакеты. Тогда позже будет непонятно, какие библиотеки нужны самому приложению, а какие пришли как зависимости других библиотек.
Лучше сначала восстановить короткий список прямых зависимостей по импортам, документации и истории проекта. Добавь его через uv add, затем сравни запуск и тесты со старым окружением. Это чуть дольше миграции одной командой, зато pyproject.toml останется понятным.
Если сервер развёртывания всё ещё принимает только requirements.txt, не нужно вести версии вручную в двух местах. Сначала экспортируй их из lock-файла в отдельный файл:
uv export --format requirements.txt > requirements-export.txt
Сравни результат со старым requirements.txt и только после проверки замени входной файл сборки. Сначала переведи локальную разработку и CI, затем меняй production-сборку отдельным шагом. Так проще понять, на каком этапе возникла несовместимость.
Как установить и закрепить версию Python
uv умеет находить системный Python и при необходимости загружать управляемую версию. Явная установка выглядит так:
uv python install 3.12
Чтобы выбрать эту версию для текущего проекта:
uv python pin 3.12
uv run python --version
uv python pin записывает запрос версии в .python-version. При этом ограничение requires-python в pyproject.toml тоже должно допускать Python 3.12. Если там указано >=3.13, uv справедливо откажется создать окружение на 3.12.
Обычно фиксируют минорную версию, например 3.12, а не патч 3.12.3: тогда uv может подобрать свежий совместимый патч. Точную патч-версию стоит закреплять только тогда, когда проект действительно от неё зависит.
Частые ошибки
Пакет импортируется через uv run, но не через python
Обычная команда python запустила системный интерпретатор или другое активное окружение. Проверь оба пути:
python -c "import sys; print(sys.executable)"
uv run python -c "import sys; print(sys.executable)"
Для проекта продолжай использовать uv run. Если программа запускается из редактора, выбери интерпретатор внутри .venv.
uv sync удалил установленный пакет
Пакет установили через uv pip install, но не объявили в проекте. uv sync выполняет точную синхронизацию с lock-файлом. Верни зависимость правильно:
uv add package-name
uv сообщает, что lock-файл устарел
Кто-то изменил зависимости в pyproject.toml, но не обновил uv.lock. Локально выполни uv lock или нужный uv add, проверь изменения и закоммить оба файла. В CI не заменяй --locked на автоматическое обновление: сборка не должна молча переписывать исходники.
После смены Python окружение ведёт себя странно
Каталог .venv расходный. После изменения основной версии Python синхронизируй проект заново; при необходимости удали только .venv и выполни:
uv sync
Не удаляй uv.lock: он описывает воспроизводимое состояние зависимостей, а не конкретный локальный каталог.
Стоит ли переходить на uv
Для нового приложения разумный базовый набор — uv init, uv add, uv run и закоммиченный uv.lock. Он заменяет ручную связку venv + pip freeze и снижает вероятность запустить проект не тем интерпретатором.
Стабильный старый проект не обязательно переносить только ради модного инструмента. Если текущие pip, requirements.txt и CI воспроизводимы, можно сначала заменить лишь команды установки на uv pip, не меняя формат зависимостей. Полный переход имеет смысл, когда команда готова считать pyproject.toml и uv.lock единственным источником состояния проекта.