Table of Contents
UV is a fast alternative to pip. It offers better speed and performance, making it a smooth replacement. To get started, just run pip install uv to download the binary.
All functions from pip are still there. Just use the command uv pip
Migrating a project
Let's explore how to migrate a project using requirements.txt and requirements-dev.txt files to UV.
Initialize with UV
Begin by creating a new UV-managed project using:
uv init
BASH
This command will create a pyproject.toml file. This file is a central configuration file in Python, introduced to standardize packaging and build processes.
Clean up the Environment
To avoid using an old virtual environment, replace it by running:
rm -r .venv/
uv venv && source .venv/bin/activate
BASH
Add your requirements
Now, add your requirements from existing files:
uv add -r requirements.txt
uv add --dev -r requirements-dev.txt
BASH
Your pyproject.toml
file should now look something like this:
[project]
name = "myproject"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"fastapi==0.115.7",
]
[dependency-groups]
dev = [
"mypy==1.14.1",
"pre-commit==4.1.0",
]
TOML
With uv sync
dependencies are installed (or uninstalled if no longer mentioned) in a virtual environment under the .venv
directory.
Additional Configurations
If your project is a package, be sure to add this:
[tool.uv]
package = true
TOML
CLI Commands
To expose CLI commands from your project, include them in the pyproject.toml file:
[project.scripts]
my-cmd = "my_project.cli:app"
TOML
Publish to PyPI
To publish your package to PyPI, you can do it manually or use automation tools like GitHub Actions or GitLab CI/CD.
UV provides a packaging Guide to assist you with this: https://docs.astral.sh/uv/guides/package/
Locally
Locally is quite simple, you just need the UV tool and a PyPI token.
First, build your package and then publish it:
uv build
uv publish --token <token>
BASH
GitHub Workflow
You can use the following GitHub workflow to publish a package to PyPI. It triggers the push-pypi
job when a tag is pushed. The version in the tag updates the pyproject.toml
file before building and publishing.
---
on:
push:
branches:
- "*"
tags:
- "v*.*.*"
jobs:
push-pypi:
runs-on: ubuntu-latest
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.13'
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Install python dependencies
run: uv sync --all-extras --dev
- name: Set release env, replace 'v' in tag
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" | sed "s/v//g" >> $GITHUB_ENV
- name: Replace version in pyproject.toml
run: |
sed -i 's/^version = "[^"]*"/version = "${{env.RELEASE_VERSION}}"/' pyproject.toml
- name: Build package
run: uv build
- name: Publish package
run: uv publish
YAML
GitLab CI/CD
Here's a GitLab CI/CD job that runs when a tag is pushed. It updates the pyproject.toml
version, builds, and publishes the package to PyPI.
---
stages:
- release
push_pypi:
stage: release
rules:
- if: "$CI_COMMIT_TAG"
- if: $CI_COMMIT_BRANCH
when: never
image: "docker.io/python:3.13-slim"
script:
- pip install uv
- projectversion=$(echo $CI_COMMIT_REF_NAME | sed 's/v//')
- sed -i "s/^version = \".*\"/version = \"$projectversion\"/" "${CI_PROJECT_DIR}/pyproject.toml"
- cat "${CI_PROJECT_DIR}/pyproject.toml" | grep version
- uv build ${CI_PROJECT_DIR}
- uv publish --token "$PYPI_TOKEN"
YAML