How to migrate from Poetry to uv
I have recently been working on a template for new Python projects and of the first decisions I had to make was which tool to use for packaging and dependency management. I initially chose Poetry since I am already familiar with it: Poetry is a mature tool that is widely used and works well. But several people have recently recommended uv as an alternative so I decided to try it. This post documents the steps I had to take to switch from Poetry to uv.
- Read more about what decisions are involved in setting up a new Python project in my post on the template
- Check out my template on GitHub
- Read the ADR I created to document the rationale for my decision to switch to uv
To summarise the outcome of my testing: uv is extremely fast (it is written in rust), manages python versions in addition to dependencies and is likely to become the new standard so I am adopting it for my new projects.
From a google search, I saw that there are tools to automate this migration (e.g. migrate-to-uv) but for a simple Python repository there are not that many steps to do it manually so that is what I did.
I also had to make additional changes to use uv in my CI/CD (GitHub workflow) pipelines, readthedocs configuration, dependabot configuration, pre-commit hooks and just recipes and to get release-please (which I am using to automate releases) to bump the version number in the uv lock file.
You can see the actual changes I made to some of the files in this pull request.
How to switch from Poetry to uv
I was using Poetry version 2.2.0 and switched to uv version 0.9.4.
Pre-requisites
- A Python project managed using Poetry (with a pyproject.toml file listing your dependencies)
- Access to a terminal
Basic steps
- Open a terminal and navigate to the root of your repository.
- Create and switch to a new branch.
- Delete the
poetry.lockfile:rm poetry.lock - Install uv:
curl -LsSf https://astral.sh/uv/install.sh | sh - Check installation (should show usage details):
uv - Create a
uv.lockfile:uv lock - Test uv run with a development tool in your repository (e.g. ruff, black, pytest):
uv run ruff check . - Change the build backend in
pyproject.tomltouv_build(or use another build system to suit your needs):[build-system] requires = ["uv-build>=0"] # or pin a version build-backend = "uv_build" - Add a module name for the build (replace
package_namewith the name of your package):[tool.uv.build-backend] module-name = "package_name" module-root = "" - Commit your changes.
Additional steps
These will be different for different repositories. Test that everything works as expected after each change.
Change poetry run to uv run
Change all poetry run commands to uv run in files that use them, e.g.:
justfile(see my template’s justfile for examples)makefiledevcontainer.json- GitHub workflows
- Pre-commit configuration file
Add a pre-commit hook for uv sync
You can add a pre-commit hook from uv to check that the uv.lock is up-to-date:
repos:
- repo: https://github.com/astral-sh/uv-pre-commit
# uv version.
rev: 0.9.4
hooks:
- id: uv-lockUse uv in your Dockerfile
If you use a Dockerfile, you can install uv by adding the following:
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
Then install your dependencies using uv instead of poetry:
uv sync --all-groups
Use uv in GitHub workflows
To use uv in GitHub workflows, replace your poetry setup with the following:
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "0.9.4"
enable-cache: true
- name: Install dependencies
run: uv sync --all-groupsUpdate dependabot config file
If you use dependabot, update the config file:
- package-ecosystem: "uv"Edit release-please configuration
If you use release-please, add uv.lock as an extra file in the release-please-config.json so that the version number of your package listed there will be bumped:
"extra-files": [
{
"jsonpath": "$.package[?(@.name.value=='package-name')].version",
"path": "uv.lock",
"type": "toml"
}
]Edit Read the Docs configuration
If you are using Read the Docs to host your documentation, edit your readthedocs.yaml to use uv to install docs dependencies:
jobs:
pre_create_environment:
- asdf plugin add uv
- asdf install uv latest
- asdf global uv latest
create_environment:
- uv venv "${READTHEDOCS_VIRTUALENV_PATH}"
install:
- UV_PROJECT_ENVIRONMENT="${READTHEDOCS_VIRTUALENV_PATH}" uv sync --frozen --group docsUpdate your README
Update your project README with instructions for how to use uv and optionally add the uv badge (
):
[](https://github.com/astral-sh/uv)
Comments