uv add or uv pip install - which?
Distortions in the uv
I’ve briefly mentioned having transitioned my Python workflow to use uv for Python version and dependency management. I want to elaborate a bit on dependency management with uv.
Let’s say I’ve started a python project with uv init
and have a pyproject.toml
which manages python version and project dependencies. To add dependencies, the options seem to be:
uv add <dependency>
oruv pip install <dependency>
or- add the dependency to
pyproject.toml
manually and then runuv sync
.
Does it matter which you choose? Yes!
Within a project, adding a dependency to pyproject.toml
manually and running uv sync
works reliably, so a valid choice in that scenario, if not the most intuitive when first starting with uv.
What about uv pip install
and uv add
- are they completely interchangeable? This github issue comment kind of answers the question, but wraps up with a statement that seems to imply it’s a matter of preference.
There may be clearer guidance but I didn’t find it right away so I thought I’d verify when each works and when it doesn’t. The result ends up being really clear, which is useful!
TL;DR
uv add
when there’s apyproject.toml
un pip install
when there’s not
Within a project
Let’s walk through this together.
Check pyproject.toml
I’ve used uv init
to start a project, which means there’s a pyproject.toml
to manage python version and project dependencies. Let’s see where we are with dependencies:
*** $ cat ../../pyproject.toml
[project]
name = "python-micrograd"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"graphviz>=0.20.3",
"matplotlib>=3.10.0",
"numpy>=2.2.2",
]
[tool.uv.workspace]
members = ["src/micrograd/my-project"]
Try uv pip install
Okay, graphviz
, matplotlib
, and numpy
are the existing dependencies. Next, I decide I want to use PyTorch and PyTorch Vision + Audio in my project. Let’s try adding those with uv pip install torch
first:
(python-micrograd) *** $ uv pip install torch
Resolved 9 packages in 517ms
Prepared 9 packages in 2.90s
Installed 9 packages in 155ms
+ filelock==3.17.0
+ fsspec==2025.2.0
+ jinja2==3.1.5
+ markupsafe==3.0.2
+ mpmath==1.3.0
+ networkx==3.4.2
+ sympy==1.13.1
+ torch==2.6.0
+ typing-extensions==4.12.2
(python-micrograd) *** $ uv pip install numpy
Audited 1 package in 2ms
(python-micrograd) *** $ uv pip install torchvision torchaudio
Resolved 13 packages in 249ms
Prepared 2 packages in 198ms
Installed 2 packages in 4ms
+ torchaudio==2.6.0
+ torchvision==0.21.0
(python-micrograd) *** $ code .
(python-micrograd) *** $ cat pyproject.toml
[project]
name = "python-micrograd"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"graphviz>=0.20.3",
"matplotlib>=3.10.0",
"numpy>=2.2.2",
]
[tool.uv.workspace]
members = ["src/micrograd/my-project"]
We see that the project’s .toml
file hasn’t been updated with those dependencies. (nb: We already saw that matplotlib had been included previously but, even if we hadn’t checked earlier, the corresponding log here shows an Audited
log message, not Resolved
, Prepared
, Installed
.)
We wouldn’t expect uv sync
to help since that synchronizes the environment with the content of pyproject.toml
:
(python-micrograd) *** $ uv sync
Resolved 13 packages in 13ms
Uninstalled 11 packages in 741ms
- filelock==3.17.0
- fsspec==2025.2.0
- jinja2==3.1.5
- markupsafe==3.0.2
- mpmath==1.3.0
- networkx==3.4.2
- sympy==1.13.1
- torch==2.6.0
- torchaudio==2.6.0
- torchvision==0.21.0
- typing-extensions==4.12.2
(python-micrograd) *** $ cat pyproject.toml
[project]
name = "python-micrograd"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"graphviz>=0.20.3",
"matplotlib>=3.10.0",
"numpy>=2.2.2",
]
[tool.uv.workspace]
members = ["src/micrograd/my-project"]
Try uv add
That went as expected. But we still want to see dependencies added to the project and we have one option remaining:
(python-micrograd) *** $ uv add torch
Resolved 37 packages in 557ms
Prepared 9 packages in 2.84s
Installed 9 packages in 165ms
+ filelock==3.17.0
+ fsspec==2025.2.0
+ jinja2==3.1.5
+ markupsafe==3.0.2
+ mpmath==1.3.0
+ networkx==3.4.2
+ sympy==1.13.1
+ torch==2.6.0
+ typing-extensions==4.12.2
(python-micrograd) *** $ cat pyproject.toml
[project]
name = "python-micrograd"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"graphviz>=0.20.3",
"matplotlib>=3.10.0",
"numpy>=2.2.2",
"torch>=2.6.0",
]
[tool.uv.workspace]
members = ["src/micrograd/my-project"]
Verify that uv add
is the way to go with pyproject.toml
Success! To recap where things stand: in the context of a Python project with a pyproject.toml
, dependencies can’t be added using uv pip install
. Let’s add another dependency:
(python-micrograd) *** $ uv add torchvision
Resolved 38 packages in 324ms
Prepared 1 package in 185ms
Installed 1 package in 4ms
+ torchvision==0.21.0
(python-micrograd) *** $ cat pyproject.toml
[project]
name = "python-micrograd"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"graphviz>=0.20.3",
"matplotlib>=3.10.0",
"numpy>=2.2.2",
"torch>=2.6.0",
"torchvision>=0.21.0",
]
[tool.uv.workspace]
members = ["src/micrograd/my-project"]
Cool. Because we used uv add
, the dependency shows up in the project’s .toml
file. We might also try adding another dependency with uv pip install
; we know the dependency won’t be added to pyproject.toml
, but can we at least run a script that imports that dependency?
import torch
import torchaudio
print(torch.__version__)
print(torchaudio.__version__)
(python-micrograd) *** $ uv run src/uv-tests/deps.py
Traceback (most recent call last):
File "/Users/msyvr/code/create/portfolio/ml/micrograd/python-micrograd/src/uv-tests/deps.py", line 2, in <module>
import torchaudio
ModuleNotFoundError: No module named 'torchaudio'
Nope. While we’re in the project environment and there’s a pyproject.toml
, a dependency can’t be used if it’s not added to the .toml
file first.
For good measure, let’s update the pyproject.toml
using uv add torchaudio
and verify that works:
(python-micrograd) *** $ uv add torchaudio
Resolved 39 packages in 221ms
Prepared 1 package in 193ms
Installed 1 package in 3ms
+ torchaudio==2.6.0
(python-micrograd) *** $ uv run src/uv-tests/deps.py
2.6.0
2.6.0
(python-micrograd) *** $ cat pyproject.toml
[project]
name = "python-micrograd"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"graphviz>=0.20.3",
"matplotlib>=3.10.0",
"numpy>=2.2.2",
"torch>=2.6.0",
"torchaudio>=2.6.0",
"torchvision>=0.21.0",
]
[tool.uv.workspace]
members = ["src/micrograd/my-project"]
As you likely expected, torchaudio
now shows up in pyproject.toml
.
No project (i.e., no pyproject.toml
)
Try uv pip install
Now, what if we leave the venv and use that same script in a non-project Python environment?
*** $ ls
deps.py micrograd-rust python-micrograd
*** $ uv run deps.py
Traceback (most recent call last):
File "/Users/msyvr/code/create/portfolio/ml/micrograd/deps.py", line 1, in <module>
import torch
ModuleNotFoundError: No module named 'torch'
*** $ uv venv
Using CPython 3.13.1
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate
*** $ vact
(micrograd) *** $ uv run deps.py
Traceback (most recent call last):
File "/Users/msyvr/code/create/portfolio/ml/micrograd/deps.py", line 1, in <module>
import torch
ModuleNotFoundError: No module named 'torch'
(micrograd) *** $ uv pip install torch
Resolved 10 packages in 103ms
Prepared 3 packages in 2.26s
Installed 10 packages in 165ms
+ filelock==3.17.0
+ fsspec==2025.2.0
+ jinja2==3.1.5
+ markupsafe==3.0.2
+ mpmath==1.3.0
+ networkx==3.4.2
+ setuptools==75.8.0
+ sympy==1.13.1
+ torch==2.6.0
+ typing-extensions==4.12.2
(micrograd) *** $ uv run deps.py
/Users/msyvr/code/create/portfolio/ml/micrograd/.venv/lib/python3.13/site-packages/torch/_subclasses/functional_tensor.py:275: UserWarning: Failed to initialize NumPy: No module named 'numpy' (Triggered internally at /Users/runner/work/pytorch/pytorch/pytorch/torch/csrc/utils/tensor_numpy.cpp:81.)
cpu = _conversion_method_template(device=torch.device("cpu"))
Traceback (most recent call last):
File "/Users/msyvr/code/create/portfolio/ml/micrograd/deps.py", line 2, in <module>
import torchaudio
ModuleNotFoundError: No module named 'torchaudio'
(micrograd) *** $ uv pip install torchaudio
Resolved 11 packages in 150ms
Prepared 1 package in 252ms
Installed 1 package in 3ms
+ torchaudio==2.6.0
(micrograd) *** $ uv run deps.py
/Users/msyvr/code/create/portfolio/ml/micrograd/.venv/lib/python3.13/site-packages/torch/_subclasses/functional_tensor.py:275: UserWarning: Failed to initialize NumPy: No module named 'numpy' (Triggered internally at /Users/runner/work/pytorch/pytorch/pytorch/torch/csrc/utils/tensor_numpy.cpp:81.)
cpu = _conversion_method_template(device=torch.device("cpu"))
2.6.0
2.6.0
Since we’d expect something similar* to work in the absence of uv, it tracks that uv pip install
is what one would use when there’s no pyproject.toml
.
*The something similar would be pip install
, as you’d expect.
Try uv add
And, finally, to confirm that uv add
won’t work outside the scope of a project (i.e., no pyproject.toml
):
(micrograd) *** $ uv pip uninstall torchaudio
Uninstalled 1 package in 36ms
- torchaudio==2.6.0
(micrograd) *** $ uv run deps.py
/Users/msyvr/code/create/portfolio/ml/micrograd/.venv/lib/python3.13/site-packages/torch/_subclasses/functional_tensor.py:275: UserWarning: Failed to initialize NumPy: No module named 'numpy' (Triggered internally at /Users/runner/work/pytorch/pytorch/pytorch/torch/csrc/utils/tensor_numpy.cpp:81.)
cpu = _conversion_method_template(device=torch.device("cpu"))
Traceback (most recent call last):
File "/Users/msyvr/code/create/portfolio/ml/micrograd/deps.py", line 2, in <module>
import torchaudio
ModuleNotFoundError: No module named 'torchaudio'
(micrograd) *** $ uv add torchaudio
error: No `pyproject.toml` found in current directory or any parent directory
Wrap up
This was a bit long, but we covered all the bases and verified when to use uv add
s uv pip install
(and also when uv sync
might be warranted).
The following simple decision tree came out of that:
- Does your Python environment have a
pyproject.toml
?
No -> uv pip install
Yes -> uv add
OR manually add dependency to pyproject.toml
and then run uv sync