How to migrate from requirements.txt to pyproject.toml with uv
To migrate a requirements.txt project to pyproject.toml, run uv init --bare to create a minimal pyproject.toml, then uv add -r requirements.txt to import every dependency. uv reads the file, writes the packages into [project.dependencies], and generates a uv.lock file that pins exact resolved versions.
For a detailed explanation of why pyproject.toml replaces requirements.txt, see why choose pyproject.toml over requirements.txt.
Prerequisites
Install uv if it isn’t already on your system.
Steps
1. Create a pyproject.toml file
$ uv init --bare
This creates a minimal pyproject.toml without sample source code or a README. If the project already has a pyproject.toml (from a tool like setuptools or hatch), skip this step.
2. Import runtime requirements
$ uv add -r requirements.txt
This command:
- Reads dependencies from requirements.txt
- Adds them to
[project.dependencies]in pyproject.toml - Creates a lockfile (
uv.lock) that pins exact versions for reproducible installs - Installs dependencies in the project’s virtual environment
Tip
If requirements.txt contains pinned versions like requests==2.31.0, uv adds the package name without the pin. The exact resolved version is captured in uv.lock instead, which is the recommended approach for reproducibility.
3. Import development requirements
If the project has a separate requirements-dev.txt (or requirements-test.txt):
$ uv add --dev -r requirements-dev.txt
This adds them as development dependencies, which are installed during development but excluded from production builds.
Verify that every dependency was imported:
$ uv pip freeze
4. Remove the old requirements files
Once the migration is confirmed, remove the old files:
$ rm requirements.txt requirements-dev.txt
If any deployment tooling still expects a flat requirements.txt, regenerate one from the lockfile on demand instead of maintaining it by hand:
$ uv export --format requirements-txt > requirements.txt
5. Manage dependencies with uv going forward
# Add a new runtime dependency
$ uv add requests
# Add a development dependency
$ uv add --dev pytest
# Remove a dependency
$ uv remove requests
# Install every dependency from the lockfile
$ uv sync
Frequently asked questions
How do I convert requirements.txt to pyproject.toml?
Run uv init --bare to create a minimal pyproject.toml, then uv add -r requirements.txt to import every dependency. uv writes the packages into [project.dependencies] and generates a uv.lock file that pins exact resolved versions. For development-only requirements files, run uv add --dev -r requirements-dev.txt.
Will uv keep my exact pinned versions?
uv adds package names to pyproject.toml without the pin (e.g., requests==2.31.0 becomes requests) and captures the resolved version in uv.lock instead. This split is the recommendation. pyproject.toml declares constraints, and uv.lock pins exact versions for reproducible installs. To keep a hard constraint in pyproject.toml, edit it manually after import or pass the pin to uv add (e.g., uv add 'requests==2.31.0').
What happens to VCS, URL, and editable entries in requirements.txt?
uv preserves them. Git URLs like git+https://github.com/psf/requests.git are rewritten as dependencies with the git source, direct URLs are stored as URL dependencies, and editable entries like -e . are dropped because the project itself is already editable when installed via uv sync. Editable paths to sibling projects (-e ../other-pkg) become path dependencies with editable = true.
Can I keep using requirements.txt alongside pyproject.toml?
Yes. Run uv export --format requirements-txt > requirements.txt to regenerate a pip-compatible file from uv.lock whenever one is needed, for Docker images, legacy deploy tooling, or AWS Lambda. The pyproject.toml and lockfile stay authoritative; the exported requirements.txt is a build artifact.
Does uv support constraints.txt files?
Yes. Pass -c constraints.txt to uv add or uv pip install to enforce version bounds without adding the constrained packages as dependencies. Constraint files are honored during resolution but do not appear in pyproject.toml.
How do I migrate a requirements.in file compiled with pip-tools?
Treat requirements.in as the source of truth and pass it to uv add -r requirements.in. uv replaces the pip-tools requirements.in to requirements.txt workflow with pyproject.toml plus uv.lock. If a flat requirements.txt is still needed for downstream tools, export one with uv export --format requirements-txt.
Related
- uv: A Complete Guide covers what uv does, how fast it is, the core workflows, and recent releases.
- Why choose pyproject.toml over requirements.txt? explains the benefits of switching
- How to migrate from Poetry to uv covers the equivalent Poetry migration
- How to migrate from Pipenv to uv covers the Pipenv path
- Create your first Python project walks through starting a new uv project from scratch
- What is a lockfile? covers how
uv.lockensures reproducible installs - What are Optional Dependencies and Dependency Groups? explains how dev dependencies work in pyproject.toml
- uv reference documents all uv commands
This handbook is free, independent, and ad-free. If it saved you time, consider sponsoring it on GitHub.