upvote
If you're the only person using the project...not really doing it wrong, your preference. If you have to share it, you can encode the supported python version(s), exclude-newer, etc, in pyproject.toml. Using a lockfile also helps against supply chain attacks - restricting the danger window to only when running upgrade rather than on any install. It also stops accidental breakages from occurring. If you lock once, you know that anyone else can install using the same lockfile, no matter what other versions have gone out in the wild. (Pyproject also can encode things like package groups, which IIRC doesn't work so well with requirements.txt)

I personally don't really use `uv add` and `uv lock --upgrade`, in the past I'd just hand edit the pyproject to pull forward my dependencies and let `uv lock` figure out the rest.

A good third of my last job was spent chasing after projects that weren't using pyproject. It typically turned multiple steps of "install python, upgrade pip, install this one special library, install requirements" inside of a Dockerfile or bash script into one `uv` command. And was more reliable afterwards, to boot!

reply
It looks like the only thing you are using uv for is to set up a virtual environment? I guess it might be installing python for you too?

Some of the things I love about uv that pip by itself doesn't give me

If you remove a package, it's dependencies get removed too

Caching. Creating a new clone or workspace is almost instant because uv has cached all the packages

Much simpler command-line than your pip examples above.

reply
If it feels wrong to use uv to manage dependencies, you don't need to go that far. Start with replacing `pip install` with `uv pip install` for a huge free speed boost.
reply