Uv - another Rust tool written to replace Pip

As a simple user of Python, uv has gotten me really excited because Charlie and his team have proven with Ruff that they have the chops to deliver and sustain an amazing tool, while really listening to the community and being thoughtful and deliberate in the design.

This is one of the first times I truly think we might get a rustup/Cargo for Python that many of us have been dreaming of that is strong enough that the community could rally around.

Many of us are rooting for you Charlie, good luck!


Using uv for the last couple of days, without doing anything more than the most routine of operations, it really does work very well as a speedy like-for-like replacement of pip.[1] Congratulations to the authors for making something that is usable right from the first release!

  1. There are a couple of snags with conda environments, but hey, early days. ↩︎


FYI, this discussion came up on uv’s issue page last night and is partly answered: What about pixi and rip? · Issue #1572 · astral-sh/uv · GitHub

Yeah, if one is following uv’s issue page and discord there’s a lot of traffic right now.

Also IMO, threads like this aren’t very inviting to people who are outside the normal Python discussion community. But that’s a discussion for a different thread.


To some extent, but I think the main reason for the proliferation of tools is the lack of functionality in existing tools, along with (ironically) the confusing landscape of competing tools. If the default tools did what people want, or if the python.org documentation more clearly pointed to tools that did what people want, there wouldn’t be such demand for new ones.

It’s true that the standards have provided some common ground for tools and allowed more tools to be developed while retaining more interoperability with one another, which is great. But I think the main reason tools arise is due to “demand” from users (of various sorts), rather than “supply” of standards.

I agree. I don’t think that “a drop-in replacement for pip” is really a great target for a new tool. It would seem to mean that the only real advantage of the new tool is speed, which is nice but doesn’t strike me as pip’s major shortcoming.

I think that that is a risky approach. It will only be immediately clear and self-explanatory if the interface exactly matches pip’s, which would then preclude making the inteface improve on pip’s. It might seem like you could just add improvements on top, but that would lead to confusion in the reverse direction, where people would expect “plain pip” to do everything that uv pip does, and get confused when it doesn’t.

It seems like the solution to that is to just come up with some new name. I guess it does lead to a bit of verbosity in the command, but I wouldn’t really see a problem with something like uv nipi install[1]. And then if the interface doesn’t wind up changing it could just be hoisted as a top-level uv command later.

Anyway, overall my response to uv is “potentially cool, let’s see what happens”. :slight_smile: I’m glad to see a project that aims to be a one-stop shop for Python packaging; I think that’s what we need. In particular I’m jazzed to see that these tools are taking (or at least aiming at taking) a “manager-first” approach[2], which I think is clearly the best way forward. At this point I still don’t see what uv and rye provide that conda does not, but they are at an early stage, so maybe that will become clearer in time.

  1. NIPI stands for New Improved Python Installer :slight_smile: ↩︎

  2. i.e., Python is managed by the environment manager, rather than vice versa ↩︎


I’m really sorry for the silence on my end – it’s not at all intentional. I had no idea that all this discussion had happened since I wrote my last reply (until @AlexWaygood made me aware – thank you Alex!), and just read through it for the first time.

I’ll make it a priority to reply at-length tomorrow – there are a bunch of good questions in this thread, but I’m just a few days behind on absolutely everything right now, and it’s also my wife’s birthday so I’m not supposed to be on the computer in the first place…


Hi! I appreciate the discussion and support here. I’ll let Charlie write the long response, but I’d like to express that I’m very interested in ensuring that our work leads more consensus in the community not less. To that end, I’d love to get to know more people invested in this space — please don’t hesitate to reach out.


Is there any way to use uv to install into the base python — i.e., not virtual — environment?

I know that tools are allowed — supposed to be! — opinionated, and indeed I understand that much of the ecosystem is (“opinionatedly”?) moving toward venvs, but it doesn’t really fit my workflow (lots of very short programs and calculations, using lots of different packages and tools, accessing data in very different locations on my disks, almost always prototyping in jupyter).

(“No, just use pip”, is a perfectly reasonable response.)

1 Like

For now, in most cases you can do VIRTUAL_ENV=$(python -c "import sys; print(sys.prefix)") uv pip install ...
For a better solution (like a --system flag), follow Cannot `uv pip install` without virtualenv · Issue #1374 · astral-sh/uv · GitHub / Add flag to allow global installs e.g. for CI · Issue #1526 · astral-sh/uv · GitHub


Thanks — I did a cursory search for relevant PRs and issues, but should have tried harder!

I’m would imagine this has already been suggested and rejected, but in case not, instead of having a subcommand at all, uv pip could simply become a different command to begin with, eg uvp. Wheels allow mutliple script entrypoints.

1 Like

There’s an issue for discussion about this at Change the name of `uv pip` · Issue #1657 · astral-sh/uv · GitHub (I also suggest uvp)


I’m going to mention an area where it becomes interesting to balance pip “bugs/features” and new feature requests from the community that users will want uv to implement.

Here’s the link. Add support for pinning a package to a specific index · Issue #171 · astral-sh/uv · GitHub

This is an area where perhaps funded support from a company like Astral could help to accelerate a standard that is provisionally approved, but not implemented, even though it will improve the security posture for everyone using PyPI. Not only pip or uv users.

I’m not sure if such a collaboration is welcome or possible, but I personally really wish it was.


Thanks for the earnest congratulations and for the interest in our work. I’m always nervous to release new things, and was especially nervous for this one, but I have been continually thankful for how welcoming the Python community has been to me. 18 months ago, I didn’t know a single person in this thread, and I’d certainly never posted on the Python forum.

There’s a lot to respond to here (again, sorry, I’m really underwater) and I’ll try to be more proactively engaged over the next few days, but I’m gonna reply to the questions that’ve come up throughout the day (and in no particular order) rather than in one big post.


Extremely useful. Like, everything here was extremely useful and referenced heavily. Same with PEP 503, PEP 691, and others. Speaking personally, a few things that come to mind with respect to challenges:

  • In implementing our PEP 517 front-end, I did have to refer back to pip and build’s source a lot to understand how those tools handle various edge cases (e.g., pyproject.toml is present but has no build-system; build-system is present but has no build-backend). We basically discovered limitations through testing and then referred back to pip and build to understand how they overcome them.

  • There was a lot of “What does pip do?” for requirements.txt, but my understanding is that requirements.txt is more-or-less pip-specific and not intended to be covered by a spec per-se. (I’m aware of the pip documentation on it, perhaps there’s more elsewhere.) For example, we had some bugs around resolving relative paths for -e vs. -r. And I didn’t realize that it supported remote URLs for requirements and constraint files. (I’ve somehow never used that feature in my entire career!)

  • There was more “What does pip do?” when investigating obscure behaviors, e.g., a --constraint file that itself includes a nested -r or -c file.

The other, related topic that comes to mind for me here is testing. This isn’t really a “standards” thing, but we did put a lot of effort into building infrastructure to test out specific, obscure scenarios, both for testing correctness and error messages. This is available as packse, which was inspired by pip-resolver-benchmarks. So, testing standards compliance was and still is hard.

The other testing-related problem that we’ve run into is that it’s hard to test against a wide range of custom indexes (e.g., Artifactory, Azure, AWS, etc.), so we unknowingly released with lack of support for some of those given odd behaviors they exhibit, but mostly around credentials and such. This isn’t really about the packaging standards as much as a challenge in practice with building a packaging tool: it’s just hard to test against a wide range of indexes without standing up a bunch of indexes yourself.


Yes! I think Zanie’s post in the uv repo covers it well, but I’ve personally chatted with folks on the Prefix team several times and (at least from my perspective) we have a good and collaborative relationship. I know it’s mentioned in the issue, but for completeness, we do already share some common infrastructure: rip uses some of the PEP-related crates that we maintain, and we use their HTTP range request crate. We’ve also been chatting around ways to collaborate further now that uv is out.

Some of the motivation for building uv comes from a difference in focus areas and priorities between the two teams. I’ll try not to speak too much for Prefix, but IIUC they’re primarily focused on the Conda ecosystem (with pixi). And support for PyPI et al (with rip) is just one slice of that. Our primary focus, meanwhile, is on the PyPI ecosystem. I knew from the start that I wanted to build something that would be familiar and easily-adoptable for folks that were already used to pip, pip-tools, etc. I also wanted to build something that was integrated yet modular, so that it could even enable usages like those we’ve seen in tox, and that required building sub-components that wouldn’t have been useful for Prefix’s use-case.

There’s probably more to write about why we went with PubGrub-rs in lieu of resolvo. Some of it is social, but not in a negative way. First, Nathaniel Smith’s posy was built around PubGrub-rs, so there was already a proof-of-concept for how it could fit into Python’s resolution model. We’re also very inspired by Cargo, and one of the primary Cargo maintainers is also one of the co-authors and primary maintainers of PubGrub-rs. (PubGrub-rs is not used in Cargo today, but there’s some desire for it to be used in Cargo eventually.) We were interested in PubGrub due to its first-class error messages, so we started talking to Jacob from Cargo/PubGrub, and there was just a lot of interest in collaborating, and in using our tool as an opportunity to stress-test and improve PubGrub-rs. We kept investing in and building around PubGrub, because we were happy with its API, performance, error message infrastructure, etc. I did a proof-of-concept where I made the resolver toggleable, and added support for resolvo, but (no disrespect intended) we didn’t see a reason to switch, since we were happy with PubGrub (especially the opportunities it unlocked for error messages) and the collaboration we have with its maintainers.


I’m curious as to whether that means you are considering any sort of plugin system? One thing we’ve had a lot of debates around with pip is extensibility - needing every feature to be built into pip has slowed progress in a lot of areas. I don’t know how a plugin system would work for uv, but we can’t really add one to pip because we don’t expose a stable programmatic API - retrofitting a plugin system “after the fact” is frustratingly hard.


N.B. I’m gonna approach my answer here without any intention of convincing you that the pip subcommand is correct. You might read it and end up feeling more opposed to the use of pip here, I’m not sure!

On the command-line interface, we don’t intend to re-implement the entire pip CLI. We won’t implement every subcommand, but we at least plan to implement a few more like list and show. We won’t implement every command-line argument, but the arguments we do support, we’ve made efforts to ensure that they follow pip’s interface (for example, we changed our --no-binary option to match pip).

(For pip-tools, I tried to add support for every argument supported on the pip-sync and pip-compile CLIs, and we then either warn or error if a user passes in an unsupported argument or an argument that already matches our defaults.)

We don’t intend to add a bunch (or any?) of additional commands under the uv pip namespace that don’t exist in pip. We do however have a bunch of arguments on uv pip install that don’t exist in pip, like --link-mode, --override, and --resolution. So we’ve taken more liberties there.

“Relative paths in requirements files” is an interesting example. We decided to implement the same behavior as pip with respect to how those paths are resolved, since it’s really important for compatibility (in fact, I got part of this wrong and fixed it based on issues that came in). However, we did one thing here that diverged from pip: we support relative paths in PEP 508 specifiers (e.g., black @ ../black) within local requirements files. I remember looking back at this issue when choosing to implement that, and feeling that it was the kind of thing pip wanted to support but was blocked on implementing.

In general, we want the uv pip interface to remain focused on compatibility, and our goal is to ship a separate higher-level interface in the future with a more opinionated workflow (something closer to Poetry or Cargo’s CLIs). So I would expect areas where we diverge from pip to instead come in the form of that higher-level interface. (For clarity: this is something we haven’t started on but plan to design and build in public.)

Regarding alternative names… assuming we were to change it, I also like uv pkg over the other proposals I’ve seen. I do think there are two separate questions here though: (1) is uv pip confusing/bad for uv users? And (2) does the use pip in uv pip cause problems for pip and other projects that aren’t uv? It’s possible that the answer to both of these is “yes” though I’ll admit that my current feeling is that when I hear constructive feedback on (1), it tends to be about convenience (why do I have to type pip each time?) rather than confusion.


I’m interested in this. I only became familiar with pip’s behavior around multiple indexes by implementing it myself and running into these same questions of precedence, security, etc. I found myself wanting to add more user control, but was hesitant to diverge from pip for compatibility and standardization reasons. I was glad to see that there’s a PEP here – how can I help?


I’d love to collaborate on a lockfile standard. I sent Brett an email this morning, so I’m just going to copy from that directly:

I also want to apologize for not reaching out earlier, per your comment in the Discuss thread. I wish I had been more proactive in chatting with you in particular. If I recall correctly, I first learned that you were thinking about lockfiles from Ofek back in early November, but I didn’t do much research into mousebender’s goals and motivations, and that’s just my fault.

More broadly (I’ll just quote it directly for transparency, but I want to reiterate that this isn’t intended as a dig at Poetry):

In terms of principles, it’s important to me that (1) we build things that are standards-compliant, and (2) we participate in the evolution of those standards. With no disrespect intended at all towards Poetry, I want to avoid finding ourselves in Poetry’s position of (1) innovating pre-standards and then (2) finding that the standards diverge from the tool’s proprietary syntax, and in a way that’s not fully compatible. Time will tell if we can achieve that, but it’s certainly my intent.


Speaking as a (very limited, and definitely atypical!) potential uv user, I do find uv pip confusing. However, at the moment that’s largely because there’s limited documentation for uv (basically just the README, I think?) and not everything is implemented. So I think in terms of “it’ll be like pip” and then get tripped up when it isn’t, or the ideas don’t match (e.g., which Python environment is it working on? Wait, it can’t be “the one it’s installed in”… so what is it? brain explodes) I don’t like the feeling of being encouraged to make assumptions that don’t always turn out to be true.

As for whether it causes problems for pip, I don’t think we can really say yet. Once uv is more widely adopted, especially by new users who maybe have limited experience with pip itself, then we’ll know.

So I guess my questions are:

  1. If using pip as the subcommand name turns out to be wrong, will it be hard to change it later?
  2. Is “closely matching pip’s behaviour, even the awkward and buggy bits” really a good goal to have?

I’ll be honest, though, a lot of my discomfort is simply because I don’t like the pip name being “stolen” for use as a generic term. It’s like I’d imagine the black maintainers would have felt if you’d used ruff black rather than ruff fmt.

I’ve probably repeated the same points enough times by now, though, so I’ll leave it at that.