# How to Migrate from conda to uv

This guide converts a [conda](https://pydevtools.com/handbook/reference/conda.md) project (defined by an `environment.yml`) into a [uv](https://pydevtools.com/handbook/reference/uv.md) project built on `pyproject.toml` and a `uv.lock` lockfile. The result: a project-local `.venv`, a cross-platform lockfile, and resolves and installs that finish in seconds instead of minutes.

Unlike the [conda-to-pixi migration](https://pydevtools.com/handbook/how-to/how-to-migrate-from-conda-to-pixi.md), there is no `--import` flag. uv reads from [PyPI](https://pydevtools.com/handbook/explanation/what-is-pypi.md), not conda channels, so the migration is a re-declaration of your dependencies rather than a file conversion.

## Confirm uv is the right target

uv fits a project whose dependencies all live on PyPI as wheels: NumPy, pandas, scikit-learn, matplotlib, SciPy, and most of the pure-Python scientific stack ship working wheels. For that stack, uv is the leaner choice and the fastest resolver available.

uv installs Python packages only. It cannot install the conda-only, non-Python dependencies conda-forge is built to provide:

- CUDA toolkits and GPU libraries resolved from conda-forge
- The standalone `gdal` package and its `osgeo.gdal` bindings, HDF5, or PROJ
- Compilers and non-Python languages (R, Julia) sharing one environment

If your `environment.yml` pulls any of those from conda-forge, migrate to [pixi](https://pydevtools.com/handbook/reference/pixi.md) instead, which keeps the project-local, lockfile-driven workflow while installing from conda-forge. See [uv vs pixi vs conda for scientific Python](https://pydevtools.com/handbook/explanation/uv-vs-pixi-vs-conda-for-scientific-python.md) and [when should I choose pixi over uv?](https://pydevtools.com/handbook/explanation/when-should-i-choose-pixi-over-uv.md) to confirm the call.

## Translate environment.yml to pyproject.toml

Start from a typical scientific `environment.yml`:

```yaml {filename="environment.yml"}
name: analysis
channels:
  - conda-forge
dependencies:
  - python=3.12
  - numpy
  - pandas
  - scikit-learn
  - matplotlib
```

Create a uv project in the same directory, pinning the Python version from the `python=` line:

```console
$ uv init --name analysis --python 3.12
Initialized project `analysis`
```

Add every package from the `dependencies:` list in one command. Packages under a `pip:` section in `environment.yml` go through the same `uv add` (they were already PyPI packages):

```console
$ uv add numpy pandas scikit-learn matplotlib
Resolved 19 packages in 321ms
Installed 15 packages in 102ms
 + matplotlib==3.11.0
 + numpy==2.5.1
 + pandas==3.0.3
 + scikit-learn==1.9.0
 + scipy==1.18.0
```

uv writes the packages into `[project.dependencies]` and captures exact resolved versions in a [lockfile](https://pydevtools.com/handbook/explanation/what-is-a-lock-file.md) (`uv.lock`):

```toml {filename="pyproject.toml"}
[project]
name = "analysis"
requires-python = ">=3.12"
dependencies = [
    "matplotlib>=3.11.0",
    "numpy>=2.5.1",
    "pandas>=3.0.3",
    "scikit-learn>=1.9.0",
]
```

Conda pins like `numpy=1.26` become a version constraint if you pass it: `uv add "numpy==1.26.*"`. Drop the pin to take the latest compatible release, as shown here.

## Map conda commands to uv

The day-to-day workflow translation:

| Conda command | uv equivalent | Notes |
|---|---|---|
| `conda create -n analysis python=3.12` | `uv init --python 3.12` | uv creates the `.venv` on the first `uv add` or `uv sync` |
| `conda activate analysis` | `uv run <command>` | `uv run python script.py` uses the project venv with no activation step |
| `conda install scipy` | `uv add scipy` | Adds to `pyproject.toml` and updates `uv.lock` |
| `pip install some-pkg` | `uv add some-pkg` | Both come from PyPI; one command now |
| `conda env export` | `uv lock` | `uv.lock` records the exact resolved versions |
| `conda env create -f environment.yml` | `uv sync` | Recreates `.venv` from `pyproject.toml` + `uv.lock` |
| `conda list` | `uv pip list` | Lists packages installed in the project venv |

To activate the environment the conda way instead of prefixing with `uv run`, source the venv directly: `source .venv/bin/activate` on macOS and Linux, or `.venv\Scripts\activate` on Windows.

## Verify the environment

Recreate the environment from the lockfile and import the packages:

```console
$ uv sync
$ uv run python -c "import numpy, pandas; print(numpy.__version__, pandas.__version__)"
2.5.1 3.0.3
```

If `uv sync` reports `No pyproject.toml found in current directory or any parent directory`, you ran it outside the project. `cd` into the directory that holds `pyproject.toml` and try again.

## Remove the old conda environment

Once the uv project works, tear down the conda environment:

```bash
conda deactivate
conda env remove -n analysis
```

Commit `pyproject.toml` and `uv.lock` so teammates reproduce the environment with `uv sync`; uv already added `.venv/` to `.gitignore`. Keep the `environment.yml` around only while other team members finish switching.

## Learn more

- [How to Install Python (and Which Method to Choose)](https://pydevtools.com/handbook/how-to/how-to-install-python.md)
- [How do uv and conda compare?](https://pydevtools.com/handbook/explanation/how-do-uv-and-conda-compare.md)
- [Which Python package manager should I use?](https://pydevtools.com/handbook/explanation/which-python-package-manager-should-i-use.md) for the full decision tree
- [uv vs pixi vs conda for scientific Python](https://pydevtools.com/handbook/explanation/uv-vs-pixi-vs-conda-for-scientific-python.md) for the package-source comparison
- [Understanding the conda and Anaconda ecosystem](https://pydevtools.com/handbook/explanation/understanding-the-conda-anaconda-ecosystem.md) for where conda-forge fits
- [How to install Python with uv](https://pydevtools.com/handbook/how-to/how-to-install-python-with-uv.md) for managing interpreters without conda
- [How to migrate from requirements.txt to pyproject.toml with uv](https://pydevtools.com/handbook/how-to/migrate-requirements.txt.md) for the pip-based path
- [uv reference](https://pydevtools.com/handbook/reference/uv.md) for the full command set
