# How to migrate from requirements.txt to pyproject.toml with uv

To migrate a [requirements.txt](https://pydevtools.com/handbook/reference/requirements.md) project to [pyproject.toml](https://pydevtools.com/handbook/reference/pyproject.toml.md), run `uv init --bare` to create a minimal pyproject.toml, then `uv add -r requirements.txt` to import every dependency. [uv](https://pydevtools.com/handbook/reference/uv.md) 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](https://pydevtools.com/handbook/explanation/pyproject-vs-requirements.md).

## Prerequisites

[Install uv](https://pydevtools.com/handbook/how-to/how-to-install-uv.md) if it isn't already on your system.

## Steps

### 1. Create a pyproject.toml file

```console
$ 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](https://pydevtools.com/handbook/reference/setuptools.md) or [hatch](https://pydevtools.com/handbook/reference/hatch.md)), skip this step.

### 2. Import runtime requirements

```console
$ uv add -r requirements.txt
```

This command:
- Reads dependencies from [requirements.txt](https://pydevtools.com/handbook/reference/requirements.md)
- Adds them to `[project.dependencies]` in [pyproject.toml](https://pydevtools.com/handbook/reference/pyproject.toml.md)
- Creates a [lockfile](https://pydevtools.com/handbook/explanation/what-is-a-lock-file.md) (`uv.lock`) that pins exact versions for reproducible installs
- Installs dependencies in the project's [virtual environment](https://pydevtools.com/handbook/explanation/what-is-a-virtual-environment.md)

> [!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`):

```console
$ uv add --dev -r requirements-dev.txt
```

This adds them as [development dependencies](https://pydevtools.com/handbook/explanation/what-are-optional-dependencies-and-dependency-groups.md), which are installed during development but excluded from production builds.

Verify that every dependency was imported:

```console
$ uv pip freeze
```

### 4. Remove the old requirements files

Once the migration is confirmed, remove the old files:

```console
$ 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:

```console
$ uv export --format requirements-txt > requirements.txt
```

### 5. Manage dependencies with uv going forward

```console
# 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](https://pydevtools.com/handbook/explanation/uv-complete-guide.md) covers what uv does, how fast it is, the core workflows, and recent releases.
- [Why choose pyproject.toml over requirements.txt?](https://pydevtools.com/handbook/explanation/pyproject-vs-requirements.md) explains the benefits of switching
- [How to migrate from Poetry to uv](https://pydevtools.com/handbook/how-to/how-to-migrate-from-poetry-to-uv.md) covers the equivalent Poetry migration
- [How to migrate from Pipenv to uv](https://pydevtools.com/handbook/how-to/how-to-migrate-from-pipenv-to-uv.md) covers the Pipenv path
- [Create your first Python project](https://pydevtools.com/handbook/tutorial/create-your-first-python-project.md) walks through starting a new uv project from scratch
- [What is a lockfile?](https://pydevtools.com/handbook/explanation/what-is-a-lock-file.md) covers how `uv.lock` ensures reproducible installs
- [What are Optional Dependencies and Dependency Groups?](https://pydevtools.com/handbook/explanation/what-are-optional-dependencies-and-dependency-groups.md) explains how dev dependencies work in pyproject.toml
- [uv reference](https://pydevtools.com/handbook/reference/uv.md) documents all uv commands
