← Back to context

Comment by FDETalkDotCom

17 hours ago

The author seems to use uv with Python (somewhat) fundamentally differently that I do.

I don't expect uv to do anything fancy. I don't run module management (installation, upgrades) through uv commands. I don't much care what uv's syntax is. I let each tool do one thing.

- Tool 1: UV makes a venv for each project, with whatever Py version is suitable for that project, so that each project's dependencies do not collide with one another.

- Tool 2: Pip installs all the requirements for a given project, within the venv for that project. From a requirements.txt file. Which, as far as I am aware, pip commands and requirements fit more of what they author is looking for.

I don't think it's necessary to subject oneself to the things the author (articulately) complains about, e.g.: uv's command syntax for listing packages; uv's emitting unbounded requirements syntax; uv's command to upgrade modules

Then again, it's quite possible the author is managing modules in projects with more complex needs than I am.

Long-winded example:

  # Make an env for the project with appropriate Python and use it
  uv venv ~/.venvs/myprojpy312 --python 3.12
  source ~/.venvs/myprojpy312/bin/activate
  
  # Make sure pip exists and is up to date
  python -m ensurepip --upgrade
  python -m pip install --upgrade pip

  # Fill in requirements.txt in readable/meaningful syntax per needs
  $ cat requirements.txt
  requests>=2.31.0,<3.0.0
  black==24.4.2
  
  # Install the requirements initially (or again after changing requirements.txt) 
  python -m pip install -r requirements.txt
  
  # List outdated modules
  python -m pip list --outdated
  
  # Upgrade modules, respecting the constraints
  python -m pip install --upgrade -r requirements.txt

And in the age of the supply chain attacks, requiring a certain staleness could be useful, too (providing time to catch recent and revoke reasonably major and recently discovered issues, though at the cost of also blocking recent fixes):

  $ cat ~/.config/uv/uv.toml
  exclude-newer = "7 days"
  # per https://news.ycombinator.com/item?id=47884491

Am I doing it wrong? Should I be thinking about `uv lock --upgrade`, `uv add`, and `uv tree --outdated` like the author? I'd rather just avoid all that, and have been able to so far.

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!

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.

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.