A couple of weeks ago, Charlie Marsh and the folks at Astral made another big splash with
a major release of UV called UV, Unified Python Packaging, which has many far-reaching features.
We had to have Charlie on the show to give us an inside look into this development.
Let's get to it.
This is Talk Python to Me, episode 476, recorded September 3rd, 2024.
Are you ready for your host, please?
You're listening to Michael Kennedy on Talk Python to Me.
Live from Portland, Oregon, and this segment was made with Python.
Welcome to Talk Python to Me, a weekly podcast on Python.
This is your host, Michael Kennedy.
Follow me on Mastodon, where I'm @mkennedy, and follow the podcast using @talkpython,
both accounts over at fosstodon.org, and keep up with the show and listen to over nine years
of episodes at talkpython.fm.
If you want to be part of our live episodes, you can find the live streams over on YouTube,
subscribe to our YouTube channel over at talkpython.fm/youtube, and get notified about upcoming
shows.
This episode is sponsored by Posit Connect from the makers of Shiny.
Publish, share, and deploy all of your data projects that you're creating using Python.
Streamlit, Dash, Shiny, Bokeh, FastAPI, Flask, Quattro, Reports, Dashboards, and APIs.
Posit Connect supports all of them.
Try Posit Connect for free by going to talkpython.fm/posit, P-O-S-I-T.
And it's also brought to you by us over at Talk Python Training.
Did you know that we have over 250 hours of Python courses?
Yeah, that's right.
Check them out at talkpython.fm/courses.
Charlie, welcome back to Talk Python to me.
How are you doing?
I'm good.
Thanks so much for having me back.
It's always a pleasure to be on here.
Well, you are certainly making waves in the Python space these days with all of your projects
and their fastness.
I think you're known as the fast Python guy these days.
Oh, that's not fast enough.
We got to use something from Astral.
The fast Python tooling guy, maybe.
Yeah.
Yeah, exactly.
Exactly.
So interesting.
You know, we spoke, I think you've been on twice before.
Is that right?
We talked about Ruff once.
Came on once to talk about Ruff.
And then I came on in March, shortly after we did the first public release of UV.
Right, right.
And UV at that time, I'll let you tell people what UV is.
But for those who know, it was kind of in the, it has pip-like features.
And now it's got another layer to the onion or another shell to it.
And that's actually why I invited you back, because there's a lot of interesting things
to talk about there.
Yeah.
Maybe like several more layers too.
Okay, well.
All right.
So let's, yeah.
Yeah.
Let's hear about them.
So first of all, I guess, you know, not everyone, believe it or not, not everyone listened to
that first Ruff interview.
Things, Ruff interview and those kinds of things.
So I suppose maybe quick introductions to you, Astral.
How'd you get to where you are?
Yeah, yeah, yeah.
So I've been working on Python tooling full-time for a little under two years at this point.
And my journey, I've been writing Python professionally for a long time.
But my journey with Python tooling started with Ruff, which is a very fast Python linter code formatter
and code transformation tool.
And what's the sort of foundational idea of Ruff was, can we make really fast Python tooling?
And so Ruff is written in Rust, but you don't need to have Rust installed or know anything about Rust to use it.
You can just install it with pip or with whatever you're using.
And that whole sort of story for me started from just working with Python a lot and asking if we could build
sort of different Python tooling by using languages like Rust.
So, you know, the first version of Ruff was very minimal, but it's grown from then to have, I don't know,
if something like 800 plus rules.
If you've used tools like Playgate or PyLint in the past, Ruff can do similar things.
So discover issues with your code without running it.
It can also fix them automatically.
And then if you've used tools like Black in the past for code formatting, Ruff can do a similar thing too,
where it automatically formats your code.
So that was how I first got started in Python tooling and also how I first ended up on Talk Python
was people were very interested in this when it came out.
And I think it broke a lot of people's minds in the sense that it really changed what was possible.
You know, maybe an analogy.
So if you have unit tests, but to run the unit test takes 30 minutes, there's no one who doesn't just want to kill time.
Who's going to say, I made a small change.
Well, let me run the test and see how that change did.
But if the tests run in 50 milliseconds, you could just set up a thing to just run the test every time code changes
and just have a green, red, white.
And I feel like Ruff did that for linting and formatting.
Like for me, for example, I have it just run Ruff on.
If I use PyCharm, I ask PyCharm to reformat the code.
It just uses Ruff to do that.
And you can check the box to just say, run it when I hit save because you won't notice a difference.
You know what I mean?
Yeah, yeah.
I think that's been one of the really interesting things about working on tooling with the focus on performance has been like,
if you build things that are way, way faster than what currently exists, like not just like a little bit, but like significantly faster.
The ergonomics of the tool just change a lot.
So maybe things that you only ran in CI before, you can now run locally.
And maybe things that you now run locally, you can run on save as opposed to on commit or on explicit command.
So that's been a big part of what we've seen with Ruff.
And the other big piece, apart from performance that I think we sort of accidentally made a lot of progress on with Ruff,
was just trying to make things simpler by bundling more stuff together.
So Ruff can do like a lot of different things.
And so you don't need to chain together as many tools to get the kind of setup that you might want to have in your Python projects.
And so a lot of the things we've built with Ruff and with UV, they've had these kind of dual goals of being much faster,
hopefully bringing in some interesting new features and functionality,
but also trying to reduce a little bit of the fragmentation and tooling and make it easier for people,
especially, you know, for newcomers who are writing Python for the first time to kind of get started.
And we have, well, you have announcements.
I have things to discuss with you about them, about making that even easier.
So that's why some of the big features of UV, right?
For example, what if I don't have Python?
Not a problem.
So that's pretty, that's pretty exciting, I think.
Yep.
Yeah.
And we'll get into that.
But I do want to just take a, not get too far past it,
because even though this episode is not about Ruff, two things.
One, a theme of Astral's is we're going to take some tools or some kind of concept that's been around for a long time,
redo it in Rust, but also not just, well, we ported over the code,
but you know, rethink some of the algorithms and some of the assumptions.
And I think that's also a lot of what makes it faster, like the way UV works with caching and things like that.
Yep.
And there's been a lot of excitement and positivity about that.
But I think there's also been a little suspicion of, wait a minute, if we write this in Rust,
is it really for Python people, by Python people?
Like what's, what's your take?
I don't, I have, I have some thoughts that are, I don't see it as a negative, but I think,
I think it's interesting just to discuss, you know, where does Rust actually belong here?
Yeah.
I mean, I think like the way I view it is that, you know, just like Python itself is,
is implemented in C, like it makes some sense for like the underlying tooling that people are using
to be written in a different language.
If it means that you can ultimately build, you know, tools that are better, you know,
at least on, on some metrics that people care about.
So like, for me, I sometimes view what we're doing as, you know, like we put all this investment
into this tooling.
We write all this stuff in Rust, which, you know, in theory, incurs some cost for us.
It's maybe, you know, maybe we move a little bit more slowly, maybe it's harder.
And in doing so, we kind of like give all these people who are running these commands,
you know, hundreds of times a day, a big boost in how they work.
And they can keep writing Python, but have a better and better experience writing Python.
So, you know, I don't think it actually really says anything personally.
I don't really think it says anything about Python that we write the tooling in Rust.
Because, you know, we get, sometimes people will criticize Python for that, but like,
you know, different languages are useful and good for different things.
And Python is an incredibly productive language.
It's like growing more and more every year.
People love writing it.
But maybe it's not the best language to write, you know, a super high performance package manager.
And that's totally fine.
Because like, we're going to do that.
And then everyone who's writing Python can benefit from it and can leverage it.
Yeah.
I do think that one interesting piece here that I got, you know, we got a lot of skepticism
around early on was like, you know, how can people in the Python community like contribute
to this if it's not written in Python?
You know, how do you like have a sustainable contributor base?
And the interesting thing for me is like, I actually think we've had a really strong contributor
base over time.
Like we have, I don't know, like somewhere between four and 500 contributors total, maybe
in Ruff.
You know, most of those are like one or two small, you know, one or two commits, maybe
just one or two time committers.
You know, but a lot of people have come to Ruff and said, you know, I want to learn Rust.
I come from the Python ecosystem.
There's a part of this that's sort of native to what I know, which is the Python language,
the Python semantics.
And it's an entry point for me to learn Rust, you know, from other people who come from Python.
So, you know, I think there is certainly a cost to engaging and a cost for contributors
because most, you know, most of our users don't know Rust.
But I don't think it's as steep as people would expect.
And I think, you know, over time we have been able to grow a pretty, a pretty healthy contributor
base, like many people who have never written Rust before.
Yeah, I agree.
And I was thinking the same thing that you pointed out that Python itself is written in
C.
Yeah.
Right.
Generally speaking, of course, there's multiple runtimes and so on and so on.
But CPython, the one that we generally use is written in C.
And I mean, I don't see why there should be an allegiance to C over Rust or anything.
And a lot of the data science tools are written in C or Orttran even, you know, something really
wild like that.
And Python is a way to kind of expose them and make them more accessible, more useful, make
people more productive on top of those, that's that native code.
Yeah.
A third example would be Jupyter, JupyterLab, Jupyter Notebook, all those things.
When you talk to the contributors of those projects, they're down in TypeScript and JavaScript
most of their day.
So the data science folks don't have to write TypeScript and JavaScript.
They just work in the tooling that's on the front end.
And so it's, you know, it's kind of like, to me, it's kind of like, let's take one for
the team.
Yeah.
We'll do this.
So we all benefit, but you don't have to.
You don't have to do it.
I actually think it's one of the kind of, one of the real strengths of Python is the interoperability
around like native code and extension modules.
It's like a big, it's actually like a big part of Python and it's a big part of why Python
has succeeded.
And I think that will actually become more, I mean, this is sort of like going off on a
tangent a little bit, but I think that will become a bigger and bigger part of like what
Python looks like and what it looks like to work with Python.
Because, you know, and I think Rust can actually play an interesting role here because at least
from my perspective, like I do not have a systems programming background.
Like I've not, I've definitely not written any C professionally.
I don't think I've ever really written any C++ and Rust was my first sort of foray into
that kind of programming.
And I think at least me, you know, for me personally, I found it much more accessible.
And so I think Rust and Python actually have this interesting story where Rust to some
degree is this kind of like superpower, low level layer that you can drop into and then
expose with a Python CLI for everyone to consume.
So anyway, my prediction is I think that will only become more and more of a part of what
Python looks like.
And that's actually, I think it's actually a good thing.
Yeah.
I do too.
Jake out in the audience, Jake Collahan, who says in another comment, great timing.
I just released a video on these changes yesterday, so that's awesome.
But the progress made in Ruff and UV sensor introductions clearly demonstrates that there's
a strong contributor base, even when it's based on Rust, right?
Yeah.
I'm not trying to dismiss that it's hard to learn Rust because I actually think it is pretty
hard to learn Rust.
And I think the learning curve is pretty steep.
But yeah, I think the thing we found is there are people who are interested and who want to
do it.
Sure.
I agree.
I think another thing that it shows regardless of Rust or not is if it's your full-time job
and there's funding and a team rather than part-time work, it can go many times faster
towards a goal than before.
I'm sure you've felt that way.
Yeah.
I mean, we're in a very unique, I mean, not completely unique, but fairly unique position
whereby we can fund people full-time to work on this stuff.
And it's actually just kind of wild to look at how much, not to sort of talk up our own
work, but just how much you can accomplish in a relatively short period of time with that
level of when people are kind of unlocked to work in that way and work on those kinds
of problems.
So, you know, just thinking it's like the amount of time we've been able to put into
rough and UV is like sort of hard to fathom for some open source projects.
It's like, wow, that's incredible.
You know, but from the perspective of a company, it's actually like quite reasonable.
And in fact, not even like that much.
So, you know, I think it's pretty like the leverage that you have with open source, like
when people are able to invest in it and really focus on it is pretty amazing because, you
know, we work on these things, we improve these things and they ship out to,
you know, I don't know, millions of users or whatever it is and really can provide a huge
boost to the ecosystem.
So, yeah, I mean, being able to work on this stuff full time, that was actually something
that I decided pretty early on with rough was the project was growing more and more popular.
And I was like, I don't know if I can keep up with this if I don't work on it full time.
And so I'm at least going to see where that where that goes.
And it's possible, right?
And here you are.
I mean, it is.
But yeah, it's I mean, I just feel like,
I just have a lot of respect for people who, you know, commit significant amounts of their
time to open source alongside everything else.
Because, yeah, it's I mean, it's an amazing thing, but it's also very challenging.
And it's definitely is.
It's 24 seven.
Well, I think it's really positive that there's a group of people putting their full effort into
especially the UV side of things.
That's going to that's going to make a dent.
Yeah, I mean, I think the other thing that's been cool about, you know, building this as a as a company is that we've been able to bring in a lot of people from like outside of Python to come and work on Python tooling.
And I think that's like a really healthy thing for the ecosystem, because not only are these people, you know, I think, like really talented and really great, but they also bring like very different ideas and experiences.
And so we have a lot of cross pollination on the team.
The team's kind of a mix of people who have who fall everywhere on the spectrum of like or axes, I guess, probably not the spectrum of like how much rust experience, how much Python experience they have.
You know, some of them have mostly worked in like TypeScript and the JavaScript ecosystem.
So that was sort of an intentional thing for me when thinking about like building a team to work on this stuff was I want to have like some people on the team who are like super deep Python experts.
And I want to have some people who like bring a totally different perspective to the problems.
So that's been another like very cool piece of putting together a team to work on this stuff.
I think that's a great perspective.
This portion of Talk Python to Me is brought to you by Posit, the makers of Shiny, formerly RStudio and especially Shiny for Python.
Let me ask you a question.
Are you building awesome things?
Of course you are.
You're a developer or data scientist.
That's what we do.
And you should check out Posit Connect.
Posit Connect is a way for you to publish, share and deploy all the data products that you're building using Python.
People ask me the same question all the time.
Michael, I have some cool data science project or notebook that I built.
How do I share it with my users, stakeholders, teammates?
Do I need to learn FastAPI or Flask or maybe Vue or React.js?
Hold on now.
Those are cool technologies and I'm sure you'd benefit from them, but maybe stay focused on the data project.
Let Posit Connect handle that side of things.
With Posit Connect, you can rapidly and securely deploy the things you build in Python.
Streamlit, Dash, Shiny, Bokeh, FastAPI, Flask, Quarto, Ports, Dashboards.
And APIs.
Posit Connect supports all of them.
And Posit Connect comes with all the bells and whistles to satisfy IT and other enterprise requirements.
Make deployment the easiest step in your workflow with Posit Connect.
For a limited time, you can try Posit Connect for free for three months by going to talkpython.fm/posit.
That's talkpython.fm/P-O-S-I-T.
The link is in your podcast player show notes.
Thank you to the team at Posit for supporting Talk Python.
One thing before we move on to talk about UV proper, closing the loop here.
You mentioned those rules, those 800 Lint rules.
And this resource you have over at docs.astral.sh slash rough slash rules is awesome.
So even if you don't use rough, you know, you care about say PEP 8 naming or something, you get a warning from Flake8 or whatever.
And it says Dunder function name.
Like what is this error, right?
What is this thing?
And then you've got each one of these rules has a, what is this?
Why is it bad?
How should you change it?
Here's the bad version.
Here's the good version.
And so on.
And I think this is just a really good resource.
I know you all put a ton of time and energy into it.
I appreciate you calling that out.
Yeah, it takes a lot of time.
I mean, once you cover all the rules, maintaining it incrementally is slightly easier.
But, you know, when we started this, we definitely had a few hundred rules.
And so, you know, it was a lot of contributors who contributed us getting to full coverage here.
It's almost like the Wikipedia of Lint rules or something.
How to Python.
Yeah.
I guess maybe one thing I'll say is like, we have a lot of rules, but you don't have to use them all.
And like the default rule set is actually pretty small.
So even when I work on projects, I don't necessarily enable all of the rules.
I typically enable like a couple subsets.
So I just think sometimes it can be intimidating to imagine 800 rules being applied over your code face.
So, you know, the default rule set is pretty small.
It covers things like unused imports, you know, things that are pretty common.
Pretty common and relatively unobjectionable.
And then we have all these different categories for ways that you kind of level up the level of coverage.
Yeah.
I take pretty much the defaults as well on all my projects, except for wider lines of code, more columns.
Yeah.
On a 32-inch monitor, 80 columns is just down the little corner.
We actually took that out of the defaults.
Did you?
Oh, beautiful.
Yeah.
I don't need a rough.toml or whatever it was I was putting in there for a configuration.
Yeah.
We got rid of that.
Because the thinking there is like, if you have long lines, they should generally be handled by a format or not a linter.
So by default, we don't enforce that.
Yeah.
Okay.
Interesting.
And then the single quotes versus double quotes, which we discussed on GitHub.
I remember, I think we talked about it last time.
Yeah, probably.
Maybe as well.
Yeah.
I talked about that with everyone.
Yeah.
And Miguel also agrees here.
Amazing docs.
The rules are top notch.
Nice work.
I appreciate that.
Okay.
So I know we're going to talk to you, V, but Tushar does have a good question out there.
And I don't know if speak to it or don't speak to it.
Are there plans for rough to become a PyLance alternative?
So a language server of some sort.
Is this anything that you're willing to talk about?
I would say, I mean, yeah, I think that's like an interesting thing that we'll consider.
It's not something that we are committed to doing or committed not to doing, like building a language server.
I would say that's probably like a few steps away from where we are today, because before we would build a language server, we would probably build, you know, something that could something like a type checker, like something that could deal with type inference and like better understand the relationships between different parts of your code.
I view that as like, it's not strictly a prerequisite to building a language server, but I view that as like a little bit more of a path.
More mypy.
Yeah, more mypy.
I think there's like a lot of interesting stuff around building a, well, first of all, of course, there's like building a type checker, but there's also building what I would call like a type aware linter.
Like you could imagine that rough itself could actually get a lot more powerful if it could do all sorts of type inference.
Like we have some rules that are only supposed to activate on dictionaries and we do some sort of bad local type inference and heuristics to figure out if we think a variable is a dictionary.
Like if you call it on it, it might be a dictionary, right?
So if we knew there's just a lot of interesting things we could do, we could build a much better tool.
So it's not just about building a type checker.
It's also about how can we build a much better linter and sort of like set of tools.
But yeah, we're thinking about that a lot.
There's a lot of discussion happening about that, both internally and publicly on the repo and the discord.
We're thinking a lot about sort of type inference and how to evolve rough in that direction.
So yeah, language server may be something we can do eventually.
It's obviously a huge undertaking.
And we want to make sure that like anything we decide to build, we feel a lot of conviction, you know, that it can be great because it's not, doesn't necessarily make sense for us to try and build something that we think is like 5% better than what's out there.
It's very hard to get users to switch to something that's 5% better.
So, you know, when we look at the opportunity set, we're kind of thinking about where can we have a big impact?
What do users really want, you know, cross-referenced against?
Where do we think there's opportunity to build something that would be an improvement in ways that users care about?
So yeah, very interesting, not something we're focused on right now, the language server piece at least.
Yeah.
You guys are going to need at least a few weeks to get to that, huh?
We're going to need a few weeks to get to language server.
All right.
I've been out there in the audience.
It says, excellent tool.
Ruff and UV have changed my life.
I've talked about Ruff.
That's very nice.
Yeah.
UV, maybe a quick summary for what it is.
And then we could talk about your post, which adds layers of features and capabilities as we start.
Yeah, totally.
So I came on the show back in March and we talked a bit about what UV was at the time.
We released UV in like mid-February.
So that was a couple of weeks after.
And UV is our Python packaging tool.
And it's built in, you know, under a lot of the same sort of design goals as we had for Ruff.
So we wanted it to be extremely fast.
We wanted it to try and bundle a few more things together so that you could use fewer tools to work with Python and be productive with Python.
And we wanted it to be really easy to adopt.
That was another principle that we thought about a lot.
So when we released UV in February, it was framed as a pip alternative.
So the idea was if you've used pip before, you know, pip install, pip uninstall, or tools like pip compile or pip sync, it should be really familiar to you.
So the API that we started with was like UV pip install, UV pip uninstall, UV pip compile.
And it was meant to kind of mirror the pip API.
And the idea there was we wanted it to hopefully be immediately obvious to people like how this tool works and what it does.
And also, I guess, to some degree what it doesn't do.
So we released that in February and it grew extremely fast.
It's yeah, it's just the adoption both in terms of like raw numbers and just like the companies that we talk to that are using it like very quickly.
A lot of people were using it.
I consider it a big success.
I'm really happy with how that went.
But it was also like, I think, a pretty small.
It was sort of a small portion of like what we wanted to build for packaging.
You know, ultimately, we weren't trying to build just a faster PIP.
I think that's like a really I think it's a really good starting point for a couple of reasons.
One, much easier for people to adopt.
Two, it required us to build a lot of the like fundamental pieces that you need for Python packaging.
Like in order to build a pip alternative, we had to be able to resolve Python dependencies, like install Python packages, understand virtual environments, right?
Manipulate all those things.
We had to implement a bunch of standards around introspecting built distributions and source distributions and virtual environments.
So we had to invest in all these things that I view as kind of like fundamental primitives of working with Python packaging.
But the ultimate goal for us was always we want to build something that's, you know, like a single static binary that you download install that just that just gives you everything you need to be productive with Python.
And from that perspective, like a pip alternative is pretty low level.
And we wanted to build something that was a little bit more high level, something that can install Python for you, something that can manage the virtual environment for you, something where you just do run this file and it figures out the dependencies, installs them.
It creates the environments and it runs this file in the environment.
Like that is what we wanted to build.
So that's what we've been building up to over the past couple of months.
Yeah.
Amazing.
Of course, you've got to have the UV pip features as a foundation, right?
Because even if you don't kind of like we talked earlier, even if you don't expose it directly as a CLI thing that from a project management perspective, it's needed, right?
Yeah.
And like, it's part of kind of like meeting people where they are to a certain degree.
Like everyone has workflows that are built around PIP, like even people that do other package that have other packaging workflows.
Often those workflows are actually built around pip commands.
And like I said, I view those as a little bit low level, like with PIP, the operations are kind of like install this package into this environment, as opposed to here are my dependencies, make sure the world is like in sync with my dependencies.
That's what I would consider to be like a little bit more high level.
So, you know, we built and released that pip interface in February.
And since then we've, you know, it's basically been like hammered, right?
By users.
So it's just gotten like better and better, right?
Because they find problems with it and then report them and it just gets, you know, it gets better.
It gets faster.
It's like more feature complete.
So we've had a few months to kind of improve and build on top of it too.
Yeah.
That's one of the benefits of such it taking, they can hold so much and people using it so much as they hit the little edge cases all the time.
Yeah.
A lot of edge cases.
It gets smoothed out quick.
I bet.
Yeah.
But it's, it's, it's, yeah, it's super fun, like set of problems to work on by the way.
And like really different from rough too.
Like, yeah, rough is rough is more like a, it's more like a compiler.
I would say like, we have like a parser and a Lexer, you know, all that kind of stuff.
And with UV, it's a lot more, how do we do IO really fast?
Like we have a lot of networking.
We're like reading and writing from disc a lot.
There's a lot of interfacing with standards.
A lot of interfacing with the registry.
Everything's async.
So it's just like a very different set of problems.
And it's, it's fun to get to kind of work on both of them.
Cause you know, they're just really different.
Yeah.
I'm sure they're both fun projects.
And there's some really good ideas and questions in the audience, but we're not ready for them.
So I think when we spoke back in March, one of the things we discussed is how you structured the CLI API in a way to leave space.
So for example, it's not UV install package.
It's UV pip install package.
And it's not UV compile --update for dependence.
It's UV pip file or whatever the command is, right?
I have it alias to a couple of letters and I never think about it again, but something, you know, that's,
you've left space in the CLI with these sub commands.
And I think now we're starting to see why you left space.
Is that right?
Yeah.
That was like pretty controversial at the time and users really hated it.
I mean, they still used it, but it's so much better.
I'll use it.
A lot of people complained about it.
I even found it, you know, I even found myself saying like, maybe we should, maybe we should stop doing this.
Like maybe we should just give up because like people, people were complaining and like I was annoyed by it and stuff.
But yeah, it's either like a huge, obviously like it's either like a terrible mistake or it was genius.
I don't, I don't actually know, but, but what it did was right.
Like one effect, which I said before was it immediately conveyed the sort of rough shape of the commands like UV pip install.
And then if you've used pip install, you know, that the next argument is like a package name or a requirements file.
But the other thing it did is it left space in the CLI for these new APIs that are sort of first class UV APIs.
So instead of, yeah, instead of doing UV install, when we released in February, it was UV pip install, which meant that today this new set of APIs that we, that we launched, let's see, two weeks ago, I think today.
Scroll up.
Is there a date there?
August 20th.
So this new set of APIs that we released are, you know, UV lock, UV sink, UV run.
They're all, they can all be top level because they're really like the first class UV workflows.
The pip API, by the way, still a hundred percent there.
And like, we're going to invest in it a lot and like continue maintaining it.
Cause like that is how most people use UV.
And maybe eventually we want that to be less true.
Right.
Like, right.
Like we hope more and more people use the new stuff.
But like, we're going to keep building that.
But for, for projects that can, we now have this new interface that if you can fit into it, it's just sort of more powerful and does more for you.
So we saved space in the CLI exactly for this reason, which is we had a bunch of stuff we knew we wanted to build.
And if we polluted, well, not polluted, it's the wrong word, but if we polluted, you know, the interface with UV install.
Clogged.
If you clogged it.
Yeah.
If we, if we lost all that space to those existing commands, it would make things harder.
So I think it's worked.
It's done.
It's had the intended effect for us of it kept the space open.
It let people use it.
It conveyed how it works.
And now they kind of exist alongside each other and the pip API, you know, you can kind of use them together in certain ways.
And when you use them together, you sort of realize that the pip API is more low level.
It's like the new APIs, you know, you have a PI project tomo file with your requirements in it and you just run UV sync and it will resolve them, create a lock file, install them in a virtual environment.
It's like one command.
You could then like modify the virtual environment.
Like you could do like UV pip install, blah, blah, blah, and like start making edits to it.
But that kind of illustrates what I mean by it's like a low level pip API is where you're kind of manually manipulating things versus these higher level APIs where you, you tell us what your dependencies are.
And then we figure everything out for you.
Yeah, that's excellent.
Just one comment on the, it's too many words or it's too long or whatever.
Like I hinted at before, I just have aliases for these.
So for example, I just type PIR and that means UV pip install dash R requirements dot TXT.
And like, I don't care if it's UV pip that or it's pip install dash, like whatever.
I don't want to type any of those.
So it's just three that PIR, let's go, you know?
Yeah.
And I've got three or four of those, you know, one to make virtual environments with UV and a couple of things like that.
And one to compile the changes and, you know, you, you look up for me, I look up the docs.
I go, okay, well, here's, here's how I'm going to shorten that to something I never think about again.
So it doesn't matter.
That's totally fine.
Right.
That's totally fine.
But you do got to consider, I guess, the workflow for new people.
Yeah.
Maybe that's a good place to talk about the features here.
So one of the things that really, there's a lot here.
One of the things that even though it's number three on the list of four things is the Python command.
So UV Python install, UV Python list, all of those kinds of things.
I mean, maybe we should start there because without that, we don't have any Python.
Although, yeah.
So that runs sort of implicitly under some circumstances, right?
Correct.
Yeah.
Okay.
So part of what we wanted to do with this release was make UV sort of self-bootstrapping,
which sounds complicated.
But the idea there is if you don't have Python installed, UV doesn't depend on Python.
It's just a binary.
So you download it.
And then when you run a command like UVVM and you give us a Python version, if you don't
have any Python installed, if you don't have that version installed, we will download and
install it for you.
So you can sort of seamlessly run these commands without worrying about how do I install Python?
Where is my Python, et cetera, et cetera.
Which means that we can achieve this really cool experience where the whole set of commands
you need to create a Python application are like, you curl install UV, and then you just
run like UV init --Python.
And we create a project for you.
We download and install that version of Python.
You can just start running things.
You don't have to think about how do I install Python?
How do I get it on my machine?
Do I have the versions I need?
Anything like that.
So you can obviously turn this stuff off, right?
And you can use your own.
It also respect pythons that you have on your machine already.
But part of the goal was we wanted to get to this, I won't call it the holy grail, but this
experience of you just download the binary, you do UV run, and everything just works.
So that was a big part of it.
And if you look at the full list of things that we put in this release, there's kind of
a lot of stuff, right?
There's like four bullets of things that each of those could be a big release.
You know, one is like the Python installation.
One is we have this sort of like tool install, kind of like pipX.
So if you want to install rough globally, you can do UV tool install rough and we'll install
it for you.
It'll get put in your path, everything like that.
We have these project management APIs that I've hinted at a little bit throughout this conversation,
like UV run, UV lock, UV sink.
Yeah, we'll get into it.
And we have, yeah, we have this thing around script execution.
So, you know, I thought for a long time, I thought that these would actually all be separate releases,
that we would do like a staggered series of releases.
And I was excited about that because, well, first of all, that's always fun.
Like you kind of like have a bunch of things and you're like shipping like one week, one
week, one week, and everyone's like, oh my gosh, we're shipping so much stuff.
But the thing we found was like, they're all kind of interconnected in subtle ways.
And like the project management and the tool API, they're just not as interesting if you
don't have like the Python.
Like they are interesting, but the fact that we have the complete story of like you do UV run
and we install Python, we've resolved your dependencies, we install your dependencies, we run the command
in the environment, like that whole picture, like everything's a little bit interconnected.
So that's how this release came to be so much stuff is we had this vision for what we wanted
the full stories to be, and they all became somewhat interconnected.
And, you know, in the end, they're all like individually, I think really powerful things,
but they kind of come together to give this, what we want this Python experience to be.
And we're not like totally there yet.
You know, we're missing stuff for sure.
But this was our attempt to capture kind of a couple of different workflows that are intertwined
in different ways.
Yeah.
I see how they all interconnect, but they are also interesting on their own, right?
Yes.
The Python installation thing is interesting.
And usable on their own, by the way.
Yeah.
Yeah, exactly.
They're all independently.
If you just had one of those, you'd be like, that's pretty cool.
Okay.
I like that.
That's pretty cool.
So let's talk just a bit more about the Python one.
So there's analogies here to other tools that people may know.
And the closest one for this would be PyE and V, do you think?
Yeah, probably.
It's like, there are obviously differences, but that's a very popular one that most, you
know, a lot of people know.
Yeah.
I'm not saying that they're identical, but it's, it fulfills a role that a lot of people
were, were solving with it.
Now, when I tried to do INV, I don't remember what I was doing wrong, but this was the early
days of Apple Silicon and maybe I had the Intel X64 version of Homebrew, but I had the build
tools for ARM.
I can't remember, but I could not get it.
Yeah.
Trying to do something under Rosetta or something.
Again, I couldn't get it to install anything with PyE and V because it would, it would download
it and would try to compile it.
Then there'd be some weird compiler bug.
And I'm like, you know what?
I'm not debugging the source of, I'm just not debugging this.
I'm out.
I'm just going to go download it.
And also that's a real, I compiled Python for some of the server stuff I'm doing and it
takes a while.
It's not that fast.
And when I get it from you guys, if I say UV Python install 3.12 or something, boom,
I get it.
Like in your standard style, it's fast.
How is it fast?
Yeah.
So that comes down to like sort of a fundamental difference between what we're doing and what
PyE.
I don't know if it's PyE or PyE by the way.
I think it's PyE by the way.
Okay.
So I'm just going to say that.
Let's go with that.
If I try to do the other, I will mess up.
So like the way that PyE typically works is, you know, it's a great tool.
A lot of people use it.
It's building Python from source and there are trade-offs around this, but the idea is it
will build the version of Python that you need.
What we're doing is we're building a top of project called Python build standalone by originally
created by Greg Sork.
And that's a project that we've started contributing to.
So I think I did the last two releases maybe.
But the idea here is we have these standalone, easily redistributable Python builds.
And when we do a release, it will create Python builds for, you know, for a bunch of Linux
architectures for macOS, for Windows on all the different Python versions.
And it will also run a bunch of optimizations over there.
So it'll do, you know, it's not these acronyms.
It's not important that you understand them, but, you know, it can do like link time optimization
or LTO and profile guided optimization, PGO.
So we build all the binaries in advance.
That's pretty impressive.
Yeah, that's impressive.
That all happens in advance.
So if you go to like the releases page here, like scroll up a little bit and just go to,
just click their latest release.
Yeah.
Right.
Yeah.
You'll see like all the, yeah, like 773 artifacts.
That's like 773 Python builds.
So it's a lot of different Pythons.
Yeah.
It's a lot of different Pythons.
Yeah.
773 different.
So like, you know, we build all this stuff.
And then when you run Python install, we figure out the correct, see, we have like arm, we
have like all this stuff.
So then we figure out the correct Python for your machine.
We just download and unzip it.
I see.
The same way you get a wheel is the way you get this.
Yeah.
I mean, it's actually the same code pretty much like under the hood for us.
Right.
It's like we stream and unzip it down into disk.
And that's great.
It's like super fast.
It's also, they're already optimized.
Like Pythons by default does not compile with optimizations.
You can compile with optimizations, but it's not what it does by default.
So these will be, you know, noticeably faster than, than what you would get by default with Pythons.
There are some downsides, like some people like to build from source, right?
They like to have like effectively the full chain of like reproducibility in the build.
And now you're kind of trusting us to give you your Pythons.
So that's, that is a downside to some people.
Yeah.
But then the next thing you do is you pip install something that has a binary wheel anyway.
So yeah, yeah, no, that is true.
There are also like a couple of quirks with these builds that we're, we're working on a little bit.
Some of it has to do with like licensing the fact that you want to have kind of
a statically, you want to have a self-contained Python.
And there are some things in the, in, you know, in there that, that require licensing changes.
So, you know, it uses all terms.
Some, there are some slight deviations from what you would get with building from source
from CPython.
And those are documented in Python build standalone.
But, you know, the general idea is we pre-build and pre-optimize these Pythons.
And then we, you know, we download them on demand and it makes it really fast.
Awesome.
When I go to python.org and download a DMG package or
and MSI for windows or whatever, it runs this installer process that takes a good long while.
And, you know, Jake just pointed out a similar experience I had.
It says it took me less than two seconds to install 3.10.
Yeah.
Same thing for 3.12.
So what is, are we missing anything compared to running a proper installer that seems to
take 20 seconds, even on a fast computer?
I think those installers also have to do some operations from source, most likely because
they're not shipping.
Okay.
I could be wrong about that.
I haven't looked at them closely.
But Python in general, like, you know, Python.org does not distribute these kind of pre-built
binary distributions for all these different architectures.
And we, there's interest in doing that.
And I'm also interested in doing that.
And, but, you know, it needs to be, you know, there are some things that need to be decided,
standards that potentially need to be set.
So, you know, it's possible that eventually we can just read, you know, grab these basically
from, from python.org.
I think our PyPy downloads come from python.org, if I'm not mistaken.
PYPy, that is.
Yeah.
Or it actually might come from PYPy.org.
Now I can't remember.
Okay.
Anyway, those come from some sort of official source.
Yeah.
So, okay.
Yeah.
Maybe eventually.
But, but for now, yeah, we're using Python built standalone and we've just been trying
to grow our familiarity with the project too.
Right.
Okay.
So let's give people a sense here, like they do not have Python at all, or they can't count
on having Python or the right version of Python.
They can run a single shell command to get UV, which UV can then manage itself.
They could pip X install the UV.
Can you homebrew?
Yeah.
What other ways, how, what other ways can I get?
Yeah, you can get UV on your machine however you want.
Like UV doesn't need to be in the virtual environment that it's manipulating.
Yeah.
It can just be anywhere on your machine and it can operate on any environment.
External tool sort of deal.
Yeah.
So once you have that.
You can install it with pip.
We have our own standalone installers that you can, you know, curl.
It's on homebrew, right?
It's on, you can, you can install with pip X, you can install it however you want.
And then ultimately it can operate on any environment on your machine.
So I actually don't recommend installing it in a virtual environment.
I recommend installing it globally.
Yeah.
That's how I have it as well.
Kind of working from there.
Yeah.
I believe I've pip X installed it.
Cause anything that falls into that category for me, it goes under pip X, at least for now.
Yeah.
Well, we'll talk about that in a minute.
Yeah.
I mean, one interesting thing is if you use our installers like the curl installers, then
you get access to self updates.
So you can run UV self update and we will update to the latest version.
That's right.
Cause I tried to really try that.
If you, yeah, you can't do that.
If you installed through a different package manager, because we don't really like know how
it was installed.
So if you install it through the installer, right.
We write a receipt that, that we understand like where we installed it and all that kind
of stuff.
Yeah.
So that's, that's one benefit.
But it's not, you're not required to do that.
Sure.
I ran into that when I, I just wanted to see what it would do.
Yeah.
And it's, it's a, you installed this from a package manager type thing.
So go do that thing.
But that's fine.
I have automation for like all those things.
So it's not a big deal.
And so on.
So to give people a sense, like once UV is on your system and in the path, you can say
UV, V and V --Python, and put up some variation of a Python version.
And if you have it great, it'll use it right to create the virtual environment.
If you don't have it, it will then do this two second download install deal.
Assuming you have fiber and then create a virtual environment based on it.
Right.
Yep.
That's right.
And you can turn that off, but that is the default behavior.
Yeah.
That's awesome.
And then you can also pass commands like managed only, I think it is, or something like that,
where you say, don't use the system Python even.
Yeah.
Only use the pythons that UV will install or like only use the pythons that are out my machine.
Ignore UV's pythons.
There's some customizations around that.
Right.
Like you could do the opposite.
I will also say this version, by the way, this version format request thing is like so hard.
Yeah.
It's just like, you'd just be shocked.
Like how much engineering work has gone into like understanding those requests and then discovering all the pythons on your machine.
Yeah.
And the discovering all the pythons on your machine part problem, by the way, is a problem that like a bunch of tools have had to solve.
And we've talked with the pythons on your machine.
And we've talked about it in different places that they could be.
And like on windows, it's also like totally different than on Unix.
So anyway, a lot of work has gone into that.
Like you can say, yeah, you can say cpython greater than or equal to 3.12.
Right.
And then we'll look for cpython rather than pypy rather than grailpy.
Yeah.
So anyway, a lot of work has gone into that.
What if I just say uvvv and I have no python whatsoever?
I think we would install the latest python.
Would you just go, yeah, just do a latest like maybe a implicit --python space 3.
Yeah.
I think that would kind of give me any python from the list of downloads.
And then we sort by version.
So I think you would effectively get the latest compatible version.
But now you're kind of quizzing me a little bit.
No, I don't mean to be quizzing you.
I'm just kidding.
All right.
So we'll move on.
I know there's so much more and we don't have a ton of time to get it.
But I just pulled up my my warp terminal and I typed uv python list and it shows me a bunch of options for arm 64 for macOS 312.5 312.0 311.9 310.3.8 and so on that I could pick.
However, I'm just wondering where your cutting edge needle or setting is going to go here.
I don't see a 3 of 13.
Yeah, we're working on it.
We're working on it.
And one of the things that is tricky about any of these package manager stories is if I homebrew it, I'll see that there's a new python, especially a major release, but I might have to wait a week before it's available on homebrew.
And but homebrew auto updated.
But if I install it for the installer from python.org, it won't auto update it.
And you know, there's just there's always a little drawback of it.
Yeah.
And so when I saw this feature, I'm like, well, if this thing could just really soon have the newest one that would just be icing on the cake.
And so what is your what is your policy on how quickly to adopt new things?
I'll go get it.
Yeah.
At least candidates and betas and things like that.
Yeah.
Like with 3.13, I mean, I would like to have it out as soon as there's an RC.
That's what I would like to do.
Okay.
Um, our policy or our, our goal is to make sure that it's out before the stable release.
Okay.
So we would like to not be lagging on the stable release.
And, you know, we view like the, the minor releases in Python, similarly in rough historically,
like we'll be like, okay, we want to make sure that we support all the 3.12 language features before 3.12 is stable.
Um, and there were like a bunch of language features in 3.12.
There was like some new grammar, there were new typing features.
And so the goal there again was like, the goal is to have it out by time.
It's stable.
So that's typically like the contract we try and uphold and that's still our plan for 3.13.
Okay.
Awesome.
Yeah.
Good to know.
Yeah.
Uh, Jay Geller says, it would be, it would be nice to have an option to install pre-release build.
And, Tushar says, the thing is Python build standalone builds 600 releases per version number.
Having that run daily is too much.
But if anyone could do some interesting caching, surely the astral folks.
You know, it's kind of amazing though.
That project runs, it's not, we like, we don't, we don't own it.
It's not under our org.
Yeah.
That project runs completely for free on GitHub action.
Wow.
Isn't that remarkable?
It's kind of crazy, isn't it?
Yeah.
GitHub is ridiculous.
Yeah.
So anyway, that's kind of.
How much traffic it handles and yeah.
Yeah.
How much data.
Yeah.
They're, they're pretty awesome.
Okay.
Yep.
So if you don't have Python, you can also, you don't have to do a V and V, you can just say,
UV Python install, give it a version.
And then you'll just have that.
Like that's what Jake and I were referring to earlier, but you can also create a V and V.
And this is sort of a philosophy that I'm, I'm getting.
And sorry, someone said this earlier, but it's scrolled off the live stream comments that this
prefer or require virtual environments by default, rather than prefer to try to jam stuff into system
Python or the core Python.
And then it could be a virtual environment if you really know the incantations.
Yeah.
That's probably like, you know, we did the release in February.
We tried to steer pretty closely to the way pit behaves to make it easy for people.
But we did pick a few battles where we wanted to intentionally diverge.
And this was, this was one of the bigger ones, which is UV by default requires a virtual environment.
So if you try and UV pip install and there's no, we can't find a virtual environment in the current
directory or an active virtual environment, we'll throw an error.
And you can opt out of that by passing a system flag, but unlike pip, right, it's opt out.
So you have to, by default, use a virtual environment and you can escape from that if you want to
intentionally.
So we're trying to, like with these APIs too, like these are all virtual environment.
Well, the tool stuff, it is, but in a different way, like UV run, UV lock, UV sync, these all create
a virtual environment in the project directory where the project is defined by a PI project tunnel.
So if you run UV run in that directory, it will look at the dependencies, resolve them, create a lock file,
create a virtual environment, install their locked versions into the virtual environment, run the
command.
And it does that every time, but it's so fast that we will hopefully so fast that we can do it.
So like if the dependencies haven't changed, it will still make sure that everything's up to date.
So if you just use UV run, we try and keep the whole environment in sync for you.
And you don't have to think about how do I manage my environment?
How do I activate it?
How do I install stuff?
But we're pretty like, we're pretty pro virtual environment.
And one thing I want to do, and it's sometimes hard to hold these lines because you have users
who come to you and want something really different.
And it can be hard not to say yes to a lot of the things that users want.
But some lines, I think we have to hold because if we can see it on them, sorry, I may sound like a
battle, but if we can see it on them, it just limits the things we can do in the future.
Like if we make things too flexible, it limits some of the things, some of the possibilities
of what we can do in the future.
And like one thing that I kind of want to change the perception around is like, I think virtual
environments are like, they're here to stay really.
And I am, so we like embrace them, but I want to change some of how people like think about virtual
environments.
In particular, I want to change this whole idea of like activating a virtual environment.
Like I want it to feel more like node modules, which people don't necessarily think, you know,
highly of node modules.
Like I think when people think of node modules, they think of a huge node modules folder with
like a ton of bloat.
But the idea there is like when you're in a project, you just sort of run commands and all the packages
just get installed there.
And it just runs in the correct environment with the correct dependencies.
And that's actually what I kind of want.
That's actually what I want Python to feel like is, yeah, there's a virtual environment,
but it's actually just kind of like the directories of, you know, it's kind of just like full
of packages, full of your dependencies.
And it just, you just use the right one at the right points in time.
So that's, that's part of the shift that I want us to move towards a little bit.
And it's part of why we're very virtual environment first and why we put the virtual environment
right in the project in a specific known place, because we want to get away a little bit from
this idea of where's the environment, how do I activate it?
Do I have the wrong one activated?
I want it to feel a little bit more like it is just sort of native to how the project works.
Okay. If you're in the context of that thing, then it just uses the right one.
Yeah.
Is it, do you have intentions to do something?
I can't remember the path, but something to the effect where if you're in a directory and
there's no PyProject, Toml or virtual environment, but if you went up one or two, if we're both,
would it fall to that one or would it just go, oh, we don't know?
We do do that with UV run.
So with UV run, we sort of find the root of the project.
Yes, exactly.
And we'll look up at parent directories.
But we don't, but if you just run Python, you know, blah, blah, blah, obviously we don't hook
into anything there.
And so, you know, like with a lot of other things, like with UV run, UV lock, UV sync,
like we, we create a virtual environment.
If you use our commands, it's kind of just like everything just works, but you can also just like
activate the virtual environment and like do whatever you want, because we're kind of trying to
embrace the fact that virtual environments are like, everyone knows, not, you know, not everyone
knows how to use them, but like people are familiar with them, editors and tooling like revolve around
them.
Right.
Yeah.
So things that try to eject from virtual environments tend to cause a lot of problems for editors and
workflows.
So part of embracing virtual environments, I think again, is like meeting the ecosystem where it is a
little bit and being like, okay, the fact that we use virtual environments and they're just like in
your project means that you don't need like a special, like editor integration to
use UV, like, you know, like PyCharm.
We'll just like let you use that virtual environment, which is a virtual normal virtual
environment.
Yeah.
That's perspective.
So that's, that's part, again, part of what we're trying to do is like build things that just
work for people, and try and embrace, you know, the standards and the conventions while also,
you know, maybe influencing or changing parts of them that we think could be, could be improved
or could be made more user-friendly.
Yeah.
I don't know why I didn't book you for two and a half hour podcast, because that's what we're going to need.
So Vincent from Comcode says, UV
run is such a game changer may work on.
He may work on a Jupyter runner for that this week.
Feels like such a game changer, which is awesome.
Cool.
Yeah.
There's a lot of cool ideas too, around this sort of, sorry, good.
Well, I was going to say with, with that in mind, let's dive into this whole project
management stuff here.
Right.
Like this is, I think this is one of the, this is one of the three big pieces of functionality
that comes.
So, and you've been talking about this sort of, some of the features like UV run and so on,
but let's, let's talk through, let's talk through like, yeah.
I want to create a new project.
Yeah.
I want to create a project.
I don't have the Python installed.
It's a new project.
I want to create a pyproject.toml, but I don't even remember the format for that.
Yep.
Let's go.
How's that work?
Yeah.
So, so we have like a series of commands that kind of manage the project life cycle
for you.
So you can run UV init to create a new project.
And it has a couple of flags based on whether you want to build like a library or command line
application, whether you want it to be structured as like a Python package, or just kind of, maybe
it's just an application that you're running on your machine.
But UV init will create the project.
You can then run UV add flask, UV add FastAPI, whatever to add dependencies.
And when you run UV add, we'll automatically generate the lock file and sync the, sync the
dependencies to your system.
So we do have commands like UV lock to generate the lock file and UV sync to download the correct
dependencies into your environment.
But you can also just kind of use these life cycle commands and UV will make sure that everything's in
the right state as you go.
So you can run UV add, UV run.
If you do UV run and then Python, blah, blah, blah, it's, it's, you know, what happens behind the
scenes is we resolve the dependencies.
We make sure the environment's up to date, and then we run that command in the environment.
So the whole life cycle of working with your project can be managed through UV init, UV add,
UV remove, UV run.
There's a lot that goes into that.
And there's also a lot of kind of powerful features built in here too.
Like when you run UV run, it accepts a flag --with, so you can do UV run dash dash
with and put a dependency there.
And it will basically just download that, put it in an ephemeral virtual environment and make
it available for the command.
So you can just pull in one off dependencies as you need to run things.
Like I, I, I never actually think about activating environments anymore.
Like most of the time when I'm running Python commands to run one off tooling, I'm running,
you know, UV run --with requirements.
And I give it a requirements file.
And then, you know, I pass the name of the file I want to run.
And like, it, it just like builds the thing you need and runs the command and then throws it away.
And because you have, again, we were talking at the beginning of this episode about how like
really fast tools change the ergonomics.
Like part of what we're trying to build here is like, if we have this packaging system, that's
really fast, especially for like repeated operations.
Like I need to keep pulling in, you know, I've downloaded this package before.
I need to download it again, use it for this one command.
Like we can just like throw away virtual environments and create new virtual environments,
you know, in like in milliseconds.
Yeah.
So if this was a Python dash M V and V sort of, it would be way too much overhead.
Yeah.
And so, you know, we can, we can just like, even like a bunch of dependencies,
like they've been installed on your machine already.
It's really, really fast just to pull these things together, use them and throw them away.
So there's just a lot, there's a lot of things that we can do.
And I think even like looking forward to the future, there's a lot of things we can do because
we have this like performance foundation.
Like, you know, I'm thinking about what if you want to test code on like a bunch of different
Python versions.
Yeah.
And maybe you don't want to like have to keep destroying and recreating your virtual
environment or something like that.
Like there's just, there's just a whole lot of stuff that we can build that would be really
hard to imagine if you didn't have a really fast tool.
Yeah.
It's, it changed.
It definitely changes what's possible.
It's too sure.
I'll put out an example that it's very near and dear to my heart.
You know what would be great?
If UV could build standalone binaries and embed Python into them.
Yeah.
That's an interesting space.
It's not something we've built anything around, but yeah, I know it's being described there.
Yeah.
I think one of the, what I've seen most of the things do is we'll do something like zip
up a virtual environment or site packages or something and, and then put that in a binary.
And then when you run it, it'll spit that out or maybe do a memory mapped sort of magic to try
to map into that and unzip it into memory or all sorts of weirdness.
And I think really for this to be easy, some somewhere along the way, I could be wrong, not
a core developer, but I feel like Python's import behavior needs to be able to import from an embedded
resource in a compiled binary rather than stick in a binary and have the binary do like weird things
where it fakes out the path.
Cause there's always like something that falls apart.
But if the pip itself like say, okay, we can import from a memory stream and not just
from file system, then these things would be like, oh, well, if that's the case, here's how you just
embed those and off it goes, you know, it'd be more like go or so here's your one thing you run it.
You know what I mean?
Yeah.
There's definitely interesting stuff to explore there.
And there's some interesting tools that exist already to try to facilitate some of those things.
Yeah.
It's also we've invested time in yet though.
Yep.
All right.
Well, yeah, I was thinking in high app is similar.
Yeah.
Py app is definitely, I've used py app before.
Actually I have an app running in my system right now.
It's in a little menu bar thing.
That's a py app app and it works well.
It does work well.
Yep.
Okay.
Um, so the project API is kind of like, you know, if you use you, if you've used like poetry or
PDM, like these tools that are oriented around working on a project, and you have a py project
toml that defines your dependencies and you might have some sort of structure.
Um, it's based around that kind of workflow of working on a project.
Um, which, you know, is that's like one way that people work with Python, but there's a
lot of ways.
There's a lot of things that people do with Python, which is why we have a couple of different APIs.
Right.
So we also have this tool API, like UV tool install, UV tool run, which we've alias to UVX.
These are for running.
This is interesting.
Yeah.
These are for running like one-off, not one-off commands, but like things that you want installed globally.
So like you might want rough installed globally on your machine so you can run it on a bunch of different projects.
We call those like tools, and you install them, you know, similar if you've used pipX before we install them into dedicated environments, and put them on your path.
Um, and there's a lot of really cool stuff here.
Like I now use UVX all the time when I want to run things.
So I'll do like UVX rough check and that translates to UV tool run rough, you know, run the check command behind the scenes.
What it does is it finds latest version of rough.
It creates an environment with that version, and then it runs the command using, using the rough binary in there.
Um, and there's very, there's really no overhead to that.
Um, if you're kind of running it repeatedly.
So, you know, this, this is oriented around like a different way of working with Python, where you have these tools that you need to run on your machine.
And you use them for different things.
Um, so we have like the project interface for working on a project, and then we have the tool interface for running Python, you know, command line tools.
Yeah.
So UVX run, well, UVX is the run version.
Yeah.
And you've also got the install.
I have some thoughts on when I might do one or the other, but the UV tool install seems like something you might want to run and have around and have auto complete in your shell.
So I could type R U tab and get rough, or I could.
Yep.
Yeah.
UV tool.
I think for things you're going to run it repeatedly, it makes a lot of sense to install them.
Um, also if you have, like, if you ran UV tool install rough, and then you ran like UVX rough, we would use the installed version.
So if you already have the tool installed, we'll still pull the installed version, assuming it's compatible with the version request that you made.
Yeah.
So like, yeah, I generally like UV tool install things that I'm going to run, you know, multiple times.
Um, the other really nice thing about UV tool install is we have UV tool upgrade.
So you can do like UV tool upgrade --all and we'll upgrade all the installed tools.
Um, so you don't have to think about like, which tools do I have installed?
Like what versions are they at?
Are they out of date?
Um, so, you know, it kind of gives you a way to manage all the Python tools that you're using,
Um, at a, at a kind of global level.
Um, so, you know, we have a lot of commands, like in our docs, we have a lot of like automation tooling
built around Python, like, you know, rough and UV are written in rust, but a lot of our like
documentation tooling, like we have a lot of scripting in Python.
Um, and all of our docs now in the doc string at the top have like the UVX command that you run to
like run the script.
Nice.
And so I just like copy that and paste that.
And then the script just runs with all of its dependencies.
So, so it's like, it's just super, it's just very, very convenient.
I think, like all these are APIs and the way they come together.
Um, and, there's a lot, I know it's a lot of different stuff.
And that was actually my biggest fear with this release was it's hard to succinctly explain
what this release is, because it's a lot of different things.
And it's not like when we released UV or in February, when we released UV in February,
it's like, this is a new tool.
It, if you know, Pip, you understand what this is, right?
It was much easier to explain, I think in a succinct way, like what we're doing.
Um, and in this release, it's like, it's actually like a lot of different stuff that comes together
to tell what I think is a very coherent story, but it's hard to succinctly explain exactly what,
what, you know, what we did.
Um, and I was very like the response to it.
I was really heartened, you know, to see that people were, people were like getting
it and they were getting different parts of it.
Like different parts of it were speaking to different people.
Um, because I actually think different parts of it are like relevant to different ways that
people work with Python.
So a lot of people were excited about, you know, the lock files, the UV run.
A lot of people were excited about the fact that we have this like scripting API.
So you can like have these standalone scripts where the dependencies are embedded in them.
And if you do UV run that script, you know, we just resolve the dependencies, download,
download them and run the command with those dependencies available, run the script with
those dependencies available.
So you can have these like hermetic Python scripts.
Um, you know, we had the Python install API.
So there were just different things that were resonating with people, which I think is what
made me happiest in the response to it.
Did you read, I'm sure you read Armin's Ryan UV August is harvest season of Python packaging.
Yeah.
That's a pretty positive take and a pretty wide ranging recommendation there.
It's, it's pretty interesting.
Yeah.
The relationship with Rye is something we get a lot of questions about.
Um, and you know, I think like,
when we, you know, when we took over Rye, the goal was always like, we want to build
UV up until to be a suitable replacement that people can migrate from ride to UV.
Um, but, and we're getting further along that path, but there's still like things we're
missing.
Um, we don't plan on like deprecating Rye any, you know, anytime soon, but all of our
like new feature development is really happening in UV and riots mostly like bug fixes, like keeping
things up to date.
Um, so, you know, Rye has actually benefited a lot from UV.
Cause it uses UV under the hood.
So like Rye has just gotten like, there's new features or there's, you know, it's gotten
faster.
Um, but you know, our goal is really to like find the things that are missing from Rye and
make sure we can support them in UV.
Yeah.
Last one we've got to cover here is you have any, points out single file scripts with dependencies.
That's the last one, the script execution.
So yeah, one of the huge problems is I, one of the reasons I think, Tushar was suggesting
it and I'm also really excited about it is if you could bundle your code into an application,
one of the benefits is you don't have to have a conversation with everyone that runs it.
Yeah.
How to do virtual environments, how to do package management, all this kind of stuff.
You just say, run, click it or, or whatever.
And somewhat short of that is I want to give you just a script of some sort, but, and just say,
run this, right?
Here's the script app.
You have an example.py to run that.
But if you put some sort of magical incantation, which it's backed by a PEP to say what it actually
requires then UV --script, something, it'll just see that and go, okay, or UV run rather.
It'll see that install the pieces ephemerally, right?
And run.
That's, that's pretty cool.
Yeah, exactly.
So as our kind of our last thing before we run out of time.
It's really cool.
This is, this is backed by a pep.
Um, I think it's seven, two, three, if I recall correctly.
So this is like a standardized, this syntax at the top of the file is standardized.
Um, might not be mentioned somewhere.
Yeah.
There's a bunch of PEP conversations, but not the one.
Not a real.
Yeah.
We sometimes try and like shy away from talking about user facing features in terms of peps.
Um, yeah.
It's because.
There you go.
It's not.
Three.
That's it.
Yeah.
Okay.
Well, there it is.
Um, but anyway, the, so the idea here is like, you can declare the dependencies for the
script, right in the script.
And then when you do UV run that script, we read that dependency data and we've run the script
in an environment with those dependencies.
Um, so, the other, I think really cool piece here
is I talked before about UV ad.
So if you're in a project with a PI project, you can do like UV ad, FastAPI or whatever,
but you can also do that for scripts.
So if you scroll, if you look for like UV ad --script.
So you referred to this like magical incantation at the top.
We will actually like create that for you.
So if you do UV ad --dash script, and then the script name and the dependencies, like we'll actually just like put that stuff in there for you.
So you don't actually have to like remember how to do that.
Like you can just do UV run ----script, and we will actually like populate that field.
So you can create a script.
You can manage the dependencies in it with UV.
You can run it.
This is like super useful.
There's some interesting conversations happening now too around like, what if we want to have a lock file for these?
Because it's a little bit different, right?
This is a, this is the list of dependencies.
It's not the list of resolved versions.
So if you wanted to have like full reproducibility, you probably want a lock file.
And the, not just these things versions, but they're the transitive closure of all the dependencies.
Correct.
You know, everything they depend on.
Yeah.
So, you know, we do that for projects.
Like if you do UV lock in a project, we create this lock file.
That's all the transitive dependencies.
It locks the exact URLs, the hashes, the versions, everything.
We don't do that right now for scripts, just because there's no,
there isn't really a place to put it.
Yeah.
But we're kind of thinking about, like you could go on scripts.
Have you considered the Windows registry?
I mean, you could always just like integrate that and import that over to Mac and Linux.
That'd be fine.
Yeah.
Just put everything in the Windows registry.
Yeah.
That's a, that's a winning idea.
Yeah.
No, I totally get it.
Yeah.
I mean, the other thing that's interesting too, is like the notebooks, like people are thinking about
how can we add this kind of functionality to notebooks and, you know, being able to declare
the dependencies for a notebook right in the notebook, being able to lock them too.
There's a lot of cool stuff that we can build now that we have all these primitives connected.
Yeah, for sure.
I mean, you could do something like take a hash of the file and then use that hash as the name
and as long as the file doesn't change, it'll run the same.
I don't know.
Yeah.
There's, I'll leave that to y'all.
So I think, I mean, we didn't even talk about the speed for some of these things and there's,
there's a whole lot of stuff here, but.
There's a lot of good stories to tell about how we made some of these things,
the problems we had to solve to like really some of this stuff, but they'll make for,
you know, if I dream they'll make for good blog posts.
In reality, they'll probably make for good Twitter threads.
Yeah.
Absolutely.
All right.
Well, Charlie, thanks for being here.
Maybe give us a final thoughts and words for folks who are interested in this, this new layer of UV.
Yeah.
I mean, I think like this is, this release is really different from the previous release in
part, because we designed and built a lot of stuff that's pretty new for people and also requires
people to, to change their workflows in a lot of cases.
Like the previous release, it was like, this is a lot like PIP.
So kind of just drop it in.
And now it's like, here's a bunch of ways to use this tools.
If you work, you, it does require you to work a certain way and kind of think a certain way,
but we think it's really powerful.
And that's all stuff we're like kind of trying to figure out.
Right.
So we're very eager for, you know, I'm sure, I'm sure all this stuff will change and I'm just
eager for like, like every release.
I'm just excited to have it out, have people testing it, have people using it so we can get feedback.
And so, you know, I, I would love for you to try it out.
I'd love you even more for you to come file issues about the things that don't work so we can make
it better and better.
But I think we have a really cool foundation here.
We can build a lot of things that hopefully make working with Python a lot, you know,
a lot easier in the sense that the tools kind of get out of your way rather than getting in your way.
So yeah, that'll be our focus for the next, for the next while is, is seeing how people are using
this stuff and seeing where we can make it better.
Well, I think it's pretty awesome what you're up to.
Big fan of UV.
So happy to see the project.
Thank you.
I appreciate it.
And always happy to have you on.
So thanks.
Thank you.
Yeah.
See you later.
Bye.
This has been another episode of Talk Python to Me.
Thank you to our sponsors.
Be sure to check out what they're offering.
It really helps support the show.
This episode is sponsored by Posit Connect from the makers of Shiny.
Publish, share, and deploy all of your data projects that you're creating using Python.
Streamlit, Dash, Shiny, Bokeh, FastAPI, Flask, Quarto, Reports, Dashboards, and APIs.
Posit Connect supports all of them.
Try Posit Connect for free by going to talkpython.fm/posit.
Want to level up your Python?
We have one of the largest catalogs of Python video courses over at Talk Python.
Our content ranges from true beginners to deeply advanced topics like memory and async.
And best of all, there's not a subscription in sight.
Check it out for yourself at training.talkpython.fm.
Be sure to subscribe to the show, open your favorite podcast app, and search for Python.
We should be right at the top.
You can also find the iTunes feed at /itunes, the Google Play feed at /play,
and the direct RSS feed at /rss on talkpython.fm.
We're live streaming most of our recordings these days.
If you want to be part of the show and have your comments featured on the air,
be sure to subscribe to our YouTube channel at talkpython.fm/youtube.
This is your host, Michael Kennedy.
Thanks so much for listening.
I really appreciate it.
Now get out there and write some Python code.
I'll see you next time.
Bye.
you
Thank you.