#453: uv - The Next Evolution in Python Packages? Transcript
00:00 Have you ever waited around for a pip to do its thing while installing packages or syncing virtual environments
00:06 or even through some higher level tools such as pip tools?
00:09 Then you'll be very excited to hear about what just got announced from Astral,
00:14 a pip compatible CLI tool called UV.
00:18 It's like pip, but a hundred times faster.
00:20 Charlie Marsh from Ruff fame and the founder of Astral is here to dive in.
00:24 Let's go.
00:26 This is "Talk Python to Me" episode 453 recorded March 12th, 2024.
00:31 (upbeat music)
00:34 Welcome to "Talk Python to Me" a weekly podcast on Python.
00:49 This is your host, Michael Kennedy.
00:51 Follow me on Mastodon where I'm @mkennedy and follow the podcast using @talkpython
00:56 both on mastodon.org.
00:59 Keep up with the show and listen to over seven years of past episodes at talkpython.fm.
01:04 We've started streaming most of our episodes live on YouTube.
01:07 Subscribe to our YouTube channel over at talkpython.fm/youtube to get notified about upcoming shows
01:13 and be part of that episode.
01:15 This episode is sponsored by Neo4j.
01:18 It's time to stop asking relational databases to do more than they were made for
01:23 and simplify complex data models with graphs.
01:26 Check out the sample FastAPI project and see what Neo4j native graph database can do for you.
01:33 Find out more at talkpython.fm/neo4j.
01:38 And it's also brought to you by us over at Talk Python Training.
01:42 Did you know that we have over 250 hours of Python courses?
01:47 Yeah, that's right.
01:48 Check them out at talkpython.fm/courses.
01:52 Hey all, I have a quick announcement before we jump into the conversation with Charlie
01:55 and sticking with the theme of the episode, I'll keep it quick.
01:58 Over at Talk Python, we just released a new free course.
02:01 It's all about working with audio in Python, converting it to text, applying all sorts of AI awesome sauce and more.
02:08 We end up with a dynamic web app that lets you have a ChatGPT style Q&A with a podcast, guests and hosts
02:16 starting from just the RSS feed.
02:19 It's really mind blowing.
02:20 As a sweet bonus, the course shows you a bunch of hands-on examples of FastAPI,
02:25 HTMX, Beanie, MongoDB and more.
02:28 I hope you love it.
02:29 Give it a look as it is 100% free, no strings attached.
02:33 The link is on the episode page, in your podcast player show notes and at talkpython.fm/courses.
02:38 Hey Charlie.
02:41 - Hey.
02:42 - Welcome.
02:43 - Yeah, thanks so much for having me back on the show.
02:44 I really appreciate it.
02:45 - Yes, it's really great to have you back on the show.
02:48 You and your team are doing awesome work these days and making a big dent in Python.
02:53 - Thank you, thank you.
02:55 Hopefully a good dent, I guess.
02:56 (laughing)
02:58 - Yeah, I guess you could make a good dent or a bad dent.
03:00 But no, I meant that in a good way.
03:02 Definitely in a good way.
03:03 - I appreciate it.
03:04 - Yeah, yeah, I think excellent work.
03:05 It's really, it's kind of surprising how some of these tools just come in
03:10 and just catch fire in a way.
03:12 I don't know how you felt about it, but it seemed more than I would have expected.
03:16 I mean, I did not expect your things to be popular, but they became really popular really quickly.
03:22 (laughing)
03:23 - Yeah, yeah, I mean, it was different with Ruff and with UV.
03:26 This sort of context around it has been pretty different because with Ruff, like when I started working on Ruff,
03:33 no one knew who I was or had any reason to care about what I was doing.
03:37 And the project just grew over time.
03:41 And then I knew that when we were working on UV, there would just be a lot more of an expectation
03:46 around like anything we build.
03:47 - Yeah, the spotlight was already shining, right?
03:49 - A little bit, yeah, yeah.
03:51 And that's awesome 'cause it means our stuff gets traction.
03:53 Also, it comes with a lot of responsibility.
03:55 It means anything we release, we're kind of committed to maintaining.
03:59 So like, it's been very interesting, like this kind of release cadence versus what happened with Ruff.
04:07 - Well, you have more people behind the scenes helping you out, right?
04:11 - I do, yeah, thankfully.
04:12 - Yeah, tell us, maybe that's a good place to just kick off our conversation is,
04:18 you know, we're talking a bit about Ruff for everyone, but in Ruff was the thing that really launched all of this,
04:24 but you started a company, Astral, got some funding behind it, building awesome tools.
04:30 Yeah, just give people the broad view of your world these days.
04:33 - Yeah, totally.
04:34 So yeah, I started, this all started when I released Ruff probably like a year and a half ago, maybe at this point.
04:43 And at that point it was really not just a side project for me, but very much an exploratory project.
04:50 Like I was kind of curious about building faster Python tooling really, and curious about getting better at Rust
04:57 and all this stuff.
04:58 And Ruff, when I released it, it's, you know, it was a lint or it is a linter,
05:05 but it kind of brings a lot of different tools together.
05:07 So if you're familiar with like Flake 8 or Pylint, but also Black, Ruff is designed to kind of bundle
05:15 all those tools together.
05:17 So it can detect problems with your code, it can fix them automatically, it can reformat your code.
05:23 So often when we see people like adopting Ruff, they're replacing like 20 or 30 tools with Ruff.
05:29 And, you know, it has, there's a bunch of nice things about it, but ultimately it's very, very fast
05:34 and hopefully a lot simpler for users.
05:37 - Yeah. - But, go ahead.
05:39 - I was gonna say, it's really nice that it's just, one tool that brings that all together.
05:44 You know, it's not a patch where, well, here's how we use isort, and here's how we use Flake 8,
05:48 and here's how we use this, and here's how we use that, you know?
05:50 - Right, I think isort's a really good example, because instead of having and isort's a great tool,
05:55 but instead of having a separate tool to do your import sorting, Ruff frames import sorting as just a lint rule.
06:01 And so you don't have to learn a bunch of different tools and figure out how to sort of merge them together.
06:06 And, you know, Ruff, again, when I released it, it was just a side project.
06:11 And it sort of took off, you know, there were, it was originally, you know, I released it in part
06:19 because I had this thesis that like Python tooling could be much faster, and Ruff was meant to evidence that.
06:25 It was meant to be an example of what I saw as like this potential to build
06:29 really different Python tooling.
06:31 And took off a couple big projects, like FastAPI and such were kind of early adopters,
06:39 and it just grew and grew and grew from there.
06:41 And I started a company, Astral, you know, shortly after based on a lot of these ideas.
06:47 So again, Ruff in this context was meant to be, you know, the goal wasn't necessarily to start a company
06:53 just based around Ruff.
06:55 The goal was to start a company based around, you know, the ideas behind Ruff,
06:59 which is can we build really different Python tooling by, well, it's all written in Rust.
07:07 It's sort of an implementation detail, right?
07:09 But ultimately what we're trying to do is build like really high performance Python tooling,
07:13 but also tooling that works together really well and simplifies things.
07:16 So tackle, it's not just about performance.
07:19 It's also about tackling a lot of, I guess what I see as the complexity in Python tooling today
07:24 and really trying to, I guess, challenge certain status quos and respect others,
07:30 but challenge some status quos in what it feels like to work with and use Python.
07:37 And so, you know, our focus as a company, you know, right now we're very, very focused
07:43 on our open source roadmap and our open source tooling.
07:47 So that's Ruff, now UV, which we'll talk about in a bit.
07:52 And these are, you know, MIT licensed, you know, fully open source tools that we build.
07:59 And ultimately our goal is to build and sell paid services that integrate really well with the tooling
08:05 and are kind of like the natural next thing you need when you're building with Python.
08:08 So, you know, we'll never charge money for like the tools themselves, those remain free permissively licensed.
08:14 But our goal is to kind of build, you know, imagine you're building with Python,
08:18 you need to deploy a web server.
08:19 There's a lot of things that you need naturally to do that.
08:22 So for people who are already using our tools, what are the natural next things they need
08:25 and how can we build really good services on top of the tooling that just integrate with it really well?
08:30 So that's kind of the premise of the company.
08:32 There's like really two focuses to the roadmap.
08:35 It's like the open source and the commercial.
08:37 And our goal is to have an incentive structure where we're just continuously aligned
08:41 to like invest a ton in the open source and grow it as much as possible in a really natural way.
08:46 - So you're not gonna do like per line fix pricing.
08:49 You get a million line fixes a month free and then, no, just kidding.
08:52 I think it's an awesome model.
08:55 And, you know, open source 10 years ago, it really looked, it was already super vibrant
09:03 and super making huge dents in the space, right?
09:07 Really a lot of people adopting it.
09:10 But I think there was kind of a funding side that was a little bit missing.
09:14 I still remember like, you know, buy me a coffee type of links, like send me 10 bucks if you like this.
09:21 And that's just, it's not a job.
09:22 That's hardly a hobby type of thing to get stuff done.
09:26 You can't have a team of people focused on it.
09:28 And it had traditionally really been around kind of a beneficial, I need to find a big tech company
09:36 that's willing to give me sufficient amount of time to work on this project to sort of fund its existence.
09:42 Or maybe I'm a consultant and I create Flask, but I consult on Flask, that type of thing, right?
09:48 And I think it's just super positive to see more direct ways people are making open source successful.
09:54 You know, I think-
09:55 - Yeah, I appreciate that.
09:56 And I wish, you know, I sort of wish that there were more good examples of that working.
10:03 There are some for sure.
10:04 You know, for me, it was pretty clear.
10:07 Like it was immediately clear to me I needed to be working on a ruff full time
10:10 if I wanted the project to succeed.
10:11 And that's kind of a microcosm of the bigger challenge, which is like we wanted to build,
10:16 like we really wanted to like professionalize the building of this, you know, the work on this project
10:22 and bring in more people to help build it.
10:24 And so, you know, ultimately it's not, obviously it's not charity.
10:28 It is venture funding.
10:29 And ultimately we need to build a business, you know, around the tooling to make it,
10:35 you know, to make it sustainable.
10:37 But, you know, again, for me, I want the incentive structure to be such that like
10:42 the open source is obviously free, open source, extremely permissively licensed,
10:47 and truly open source.
10:50 Like we have tons and tons of contributors.
10:52 We have a huge community around it.
10:54 And I'm just glad that we've been able to bring in more people to kind of supercharge
11:01 the development of it all.
11:02 So yeah, so I guess you talked on this before, but we're now eight people.
11:08 So we've grown, you know, it was, I guess a year ago it was just me in March.
11:14 So over the past, yeah, our first two team members joined actually in March
11:20 of last year, so almost exactly a year.
11:22 And yeah, we're completely distributed.
11:24 So we're, you know, we have people in US Pacific time all the way to Bangalore.
11:31 So we're just, you know, around the like open source, like we're kind of all over the world
11:37 and just building, you know, building all this stuff out in the open.
11:41 - It's such a good fit to be a distributed company as an open source with open source roots,
11:47 because the tools of open source, in some degree for software in general,
11:51 but especially for open source is asynchronous, semi-connected, you know, kind of the Zen of get,
11:58 but for the way you work, right.
12:00 And it makes it super easy to hire just the most engaged people, regardless of where they are.
12:04 - Yeah, exactly.
12:05 - Rather than the people who are willing to commute to my office in the office park.
12:08 - Yeah, it was, I would be pretty surprised if a single person I've hired
12:14 would have been willing to move to New York, which is where I'm based.
12:19 So from that perspective, it was a no brainer, which is, and actually, you know, multiple people we've hired,
12:26 our relationship with them started on the repo.
12:29 - Yeah.
12:30 - In rough itself.
12:32 And then almost everyone we've hired, we discovered through open source in some way
12:38 or had some relationship through open source in some way.
12:40 - Yeah.
12:41 - So yeah, it's been a really, it's very much in, it's also very much in the DNA of the company,
12:46 which is, you know, we actually also intentionally try to hire people who have been maintainers, right?
12:51 And have a lot of experience with that too.
12:53 We view that as a really important skill.
12:55 - Yeah, that's excellent.
12:56 So we talked about rough.
12:59 One thing I do wanna give a bit of a shout out to is, I don't remember, I think I found this on Mastodon,
13:05 I can't remember where somebody talked about it, but one of the things that ruff does,
13:10 one, it changes code, which is awesome.
13:12 I love your ruff format story, but it also just tells you, hey, this could be better.
13:16 You're violating PEP 8, you're violating this other convention or even a security thing, right?
13:22 But the why of that, I think requires a little bit of experience.
13:26 Like, why should I use this kind of loop or that kind of comprehension over another, right?
13:34 People told me that who are much better have been doing this longer, I shouldn't do it.
13:38 Why?
13:39 When you have 700 rules, there's a lot of why.
13:42 And so you guys came up with this thing at docs.astral.sh/ruff/rules, put in links that literally for each one of these
13:51 has like a little example and what is good and what is bad and when you should use it and so on.
13:57 You wanna just tell people about this a bit?
13:59 I think it's a massive--
14:00 - Yeah, totally.
14:01 So we didn't have, I mean, we obviously didn't have this when we started the project
14:04 and then we accumulated a lot of rules.
14:08 When we decided to add this, I think we already had like hundreds of rules
14:12 and the motivation for the format really comes from Clippy, which is the linter used in Rust.
14:20 - Okay.
14:21 - And they have really, Rust in general has a really good documentation culture
14:25 and Clippy has this nice format, very similar to ours.
14:27 We've made some adjustments, but it's pretty similar around how you document lint rules,
14:32 like what's the motivation and giving examples.
14:35 And so we were like, all right, let's, we wanna do this.
14:37 And we just over a very long period of time and a lot of contributors contributed on this documentation,
14:43 but it took like six months or something probably to document it all. - I can imagine.
14:46 - And now, yeah, now we can, now we require it for all rules.
14:49 So it's much easier to add going forward, but it was a huge effort to add this.
14:54 And some of the explanations too are very extensive and detailed with lots of references.
15:01 - Yeah.
15:02 Yeah, I pulled the one up for isort, unsorted imports, which is error I001.
15:08 And it also talks about whether it can automatically fix it, what this does, why is it bad?
15:13 So it says things like consistency is good.
15:15 Use a common convention for imports to make your code more readable and idiomatic or Pydantic.
15:20 And it just gives an example, bad, good.
15:23 - Right, right.
15:24 - I think that's nice.
15:25 - Yeah, and we've started to put more stuff in here over time too, like whether, like in some cases,
15:30 we let users apply automatic fixes that aren't completely safe, like by opting in,
15:36 like it might change the meaning of your code and you kind of need to be careful.
15:39 And so over time, we've started to document that here too, like rules that have unsafe fixes, why?
15:44 Like in what case might it break your code and what should you look out for?
15:48 So yeah, we want it to be a tool with really good, like we're kind of inspired by Rust in this way
15:56 'cause Rust has a really good documentation culture and also the Rust like compiler itself
16:00 has really good error messages.
16:02 It's sort of famous for that.
16:03 Like when your code doesn't work, it's really good at telling you why.
16:06 Doesn't always get it right, but it has famously good error messages.
16:09 And that's something that we try and channel too, to like when we make changes to configuration,
16:14 like just putting extra effort into trying to make like those like error messages and those hints helpful.
16:19 But yeah, it's a lot of work.
16:20 So I appreciate that you called it out.
16:22 - I'm sure it looks like a lot of work, but it's one of those things that's,
16:28 where else are you gonna get this knowledge, right?
16:29 I mean, I know you can go search for one at a time, but in this aggregate, this is really good.
16:34 - Right, right, right.
16:36 This portion of Talk Python to Me is brought to you by Neo4j.
16:40 Do you know Neo4j?
16:42 Neo4j is a native graph database.
16:45 And if the slowest part of your data access patterns involves computing relationships,
16:50 why not use a database that stores those relationships directly in the database,
16:55 unlike your typical relational one.
16:57 A graph database lets you model the data the way it looks in the real world,
17:00 instead of forcing it into rows and columns.
17:04 It's time to stop asking a relational database to do more than they were made for
17:08 and simplify complex data models with graphs.
17:12 If you haven't used a graph database before, you might be wondering about common use cases.
17:16 You know, what's it for?
17:18 Here are just a few.
17:19 Detecting fraud, enhancing AI, managing supply chains, gaining a 360 degree view of your data
17:26 and anywhere else you have highly connected data.
17:30 To use Neo4j from Python, it's a simple pip install Neo4j.
17:35 And to help you get started, their docs include a sample web app demonstrating how to use it both from Flask and FastAPI.
17:43 Find it in their docs or search GitHub for Neo4j movies application quick start.
17:47 Developers are solving some of the world's biggest problems with graphs.
17:51 Now it's your turn.
17:52 Visit talkpython.fm/neo4j to get started.
17:57 That's talkpython.fm/neo4j, the number four and the letter J.
18:02 Thank you to Neo4j for supporting Talk Python to Me.
18:05 So Ruff will fix a lot of these things for you.
18:09 And one of the things that I like to do is I just have it integrated into my editor these days.
18:15 So both with PyCharm and with VS Code, if I just say format this document, that's Ruff format.
18:21 - Nice.
18:22 Yeah, yeah.
18:23 So we have a VS Code extension and it supports formatting, auto fixing, all that kind of stuff.
18:31 - The PyCharm one's a, JetBrains one's a third party one, right?
18:35 Someone else decided to make that?
18:36 - Yeah, the JetBrains one is by Udai.
18:40 And it's, yeah, that's like a community extension.
18:45 We're considering doing our own at some point because there's a lot of demand for,
18:50 obviously we have a lot of users who use the JetBrains stuff.
18:53 I mean, I use it.
18:55 So we may do it and do our own at some point, but there's a community maintained one right now.
18:58 And that's based on, we have a sort of like a language server.
19:02 So there's kind of like an underlying piece of technology that wraps Ruff that powers all of these editor integrations.
19:08 So like, you can also use that from like NeoVim or like Sublime Text or Emacs,
19:13 like all of those editors support the LSP.
19:16 And so you can actually, it's the same thing that powers the VS Code extension,
19:20 just that's wrapped in some VS Code specific stuff, but like it's the same piece of technology.
19:26 And we're actually rewriting that right now to make it sort of like more natively integrated into Ruff,
19:33 which will let us do some cool things.
19:34 So it should get like actually significantly better, I think over the course of this year,
19:39 'cause it's becoming more and more of a priority for us.
19:42 - Yeah, cool.
19:43 The whole LSP thing is pretty interesting.
19:45 I think it's really opened up a lot of editors being better.
19:48 - Yeah, it has.
19:49 And it made it like from our perspective, it made it way easier to build like editor integrations
19:55 because we just built an LSP and then it like works for like everyone almost.
20:01 - Yeah.
20:04 - Like the JetBrains stuff, it does support the LSP, but I think only in the paid version,
20:10 not in the community version.
20:11 So like there's some limitations around it, but in general, like if you support the LSP,
20:15 like it's actually very easy to build editor integrations that work with everyone, which is like super, super useful.
20:21 - Yeah, sort of rebuilding your own integration for every single thing, which is not fun.
20:26 - Yeah, it's a lot.
20:27 - All right.
20:28 Well, let's talk about the main project here.
20:32 The main reason for being here today is UV.
20:36 Tell people what UV is.
20:37 This is your next big project, next big tool.
20:40 - Yes, yeah.
20:41 UV, we released UV a little under a month ago.
20:46 And this is something that I've wanted to do, like basically since we started the company,
20:53 I wanted to start, I thought there was an opportunity to build some really interesting tooling
20:58 in Python packaging.
21:00 And UV is kind of the first milestone in that.
21:03 So UV in its current form, it's designed as a sort of drop-in alternative
21:12 to pip, pip tools, like if you use pip compile, pip sync and virtualenv.
21:17 So it takes those three tools and tries to bundle them into one.
21:22 And so it can do things like, given a set of input requirements, generate a requirements.txt file,
21:30 similar to what you'd get from pip compile.
21:33 It can, you can do UV pip install -r requirements.txt, UV pip install black.
21:40 So it's really intended right now to be a sort of, it won't always, we don't support absolutely 100% of what pip does,
21:51 but it's, we try to be pretty close.
21:53 And so in many cases, the intention is that people can basically drop in UV
21:59 in their project that uses pip today and get in many cases, like very, very significant performance improvements.
22:08 So similar to ruff, like some of the goals we had for this project were one,
22:12 it should be very, very fast.
22:15 And UV, it's really fast.
22:18 In particular, there's like a benchmarks.md in here, actually, if you want to click on that.
22:26 Now scroll up.
22:27 - Does that do it?
22:28 - Oh yeah, that works too, I guess.
22:30 That was smart of me.
22:31 Yeah, so it's really, really fast, especially if you've already have, if you're, if you have things cached,
22:41 which is pretty common.
22:41 So like often on your machine, when you're doing like pip install -r, whatever,
22:47 a lot of those packages, you've probably installed them at least like once before
22:50 on your machine, or maybe you deleted your virtual environment and you're recreating it with the exact same dependencies
22:57 or something like that.
22:58 UV is like very, very well optimized for that case.
23:02 So if you have a package that you're installing multiple times, like the installation is effectively free.
23:09 And it's also a lot more like disk space efficient.
23:12 We use kind of like, we store all of them in one place and kind of copy them into your virtual environment
23:17 so that you don't have like many, many different copies of the package too.
23:20 So this was all kind of taking techniques and inspiration from like other ecosystems
23:27 and other package managers and kind of molding them to fit Python's model
23:32 for how packaging and dependencies work and all the specifications.
23:37 And so again, the end result is like you, installing into a virtual environment,
23:42 a package that you've already installed before is basically free.
23:45 And yeah, a lot of these things are just like way, way, way faster.
23:49 Similar to ruff like-
23:51 - Dramatically faster, yeah.
23:53 - Yeah, and similar to rough like-
23:54 - Dramatically, and I think, you know, it's worth pointing out that like on one hand,
23:59 we all have an extra 10 seconds, right?
24:01 Or whatever. - Of course.
24:04 - But in the aggregate, all of these things are just like little paper cuts
24:08 over your day, you know?
24:09 And so, yeah, sure, I can format the code and I could use something nice
24:13 and sure if it takes 20 seconds, okay.
24:16 But then you stop running it 'cause it's kind of a hassle and you're just,
24:18 you're in your flow.
24:20 And this is kind of the same way.
24:22 It's like, oh, I wanted maybe see if there's a new, some new packages for this project
24:26 as I'm sitting down to work on it.
24:28 Like, okay, well, wait for a pip compile to run and you wait and you wait and then like,
24:33 okay, now it's done onto the development version and you wait and you wait.
24:37 And like, you know, it's just some of these things that are instant.
24:41 - Just ask the question more and it just doesn't break your train of thought, you know?
24:45 - Totally.
24:46 I think there's like, maybe like three different things that come to mind here when we think about performance.
24:51 'Cause like, yeah, okay, in this case, like it may not seem to change your life
24:55 if you're going from one second to, you know, 50 milliseconds.
24:59 But I think three things come to mind.
25:00 So one, like for companies and large projects, this can actually be like a really big difference.
25:06 And so if you're at a company and you have like a big monorepo with like a bunch of different sub projects
25:13 and they all have requirements files and you wanna bump a dependency, that can be like, at that point you're talking
25:18 like 15 plus minutes for a command.
25:22 And so like, the larger the project gets, obviously the more performance matters
25:26 and the more it helps out.
25:28 And we're trying to build tooling that can basically scale, I don't know about like to arbitrarily large projects,
25:32 but like to large projects and useful for companies too.
25:35 You know, the other thing I'd say is I think there's something that happens like when tools,
25:42 when you make something like way faster, it just changes a lot of the ergonomics
25:46 around what it's like to do things.
25:48 And so, you know, in this case, like, okay, so installing into a virtual environment,
25:54 a package that you've already installed before is free now.
25:57 And so how does that change things?
25:59 It's nearly instant.
26:00 So how does that change things, right?
26:01 So that means like, if you mess up your virtual environment and have to delete it and recreate it,
26:06 it doesn't cost you anything.
26:07 It's totally ephemeral.
26:09 You can throw it away and recreate it at any time.
26:11 And like, that's just like a different, like it sounds small, but that's kind of like a different relationship
26:15 to a virtual environments than before, where it's like, okay, I created the virtual environment now.
26:18 Oh no, my virtual environments have messed up.
26:20 I got to recreate it.
26:21 Like we want to just change a lot of the dynamics around some of those like abstractions.
26:25 And then the other thing is this performance budget or this, if you think of performance like a budget,
26:30 this buys us a lot of room.
26:32 And so like the fact that we are so fast on some of these things means that we can do things
26:39 that otherwise might be like prohibitively slow.
26:41 And this is more sort of forward-looking and for the future.
26:44 Like one thing that we're thinking about a lot right now is this idea of like resolving Python dependencies
26:49 for many platforms, because it's a little bit complicated, but you know, pip compile and pip and UV,
26:56 they're really designed to only work on like the current Python platform
27:00 and the current Python that you're using.
27:02 So if you're on like macOS and you run pip compile, or UV pip compile, it will give you dependencies
27:08 that are correct for like macOS and your current Python version, but they might be wrong on Windows because Python,
27:16 in Python you can have dependencies that vary based on things like the current Python version
27:20 or the current operating system.
27:22 - Yeah, so one example would be a UV loop, right?
27:26 For people who are trying to speed up.
27:27 - I think it doesn't work on Windows.
27:29 - It doesn't work at all on Windows, that's right.
27:31 And so.
27:31 - Yeah, so that's a very common one.
27:33 - Yeah.
27:34 And it is, I think very common that this hap, that, you know, this is a very common thing,
27:38 like on like lots of really, really popular packages have these kinds of marker.
27:43 These were called markers, which basically makes the dependencies conditional
27:47 based on the current Python.
27:49 And so, you know, like again, like in pip and pip tools, UV right now just locks for the current Python.
27:57 Poetry and I think PDM, but poetry for sure does this very interesting thing
28:03 where they actually try to lock, they try to resolve for like all possible platforms.
28:08 And that's something, it's really convenient because it means that like you kind of do one lock
28:14 and then any user anywhere can like use that and it works.
28:18 And it's kind of like guaranteed to be right as opposed to maybe it doesn't work on Windows
28:24 or whatever else.
28:24 And so we're pretty interested in like that, adding that behavior and that's gonna be like more expensive.
28:30 And so if we have something that's really fast right now, it kind of like opens up a design space
28:35 of interesting things we can do to solve that problem while still being, you know, very fast.
28:41 So that's kind of how I think about performance.
28:44 Like I think people like a little bit underrate how much of an impact it can have
28:49 on even small interactions.
28:51 'Cause once you try something that's much faster, it's often hard to go back to the other thing.
28:55 But I'm glad you've had that experience at least.
28:59 - Yeah, absolutely.
29:00 A couple of interesting comments.
29:02 Dane says, "If it takes 10 seconds, "I go to triage that issue on GitHub
29:06 "and come back five minutes later." Right, like that's kind of where I was getting at
29:09 with the flow stuff.
29:10 It's like, okay, I'm ready to go.
29:12 Mind wonders and you're kind of like starting over.
29:15 - Yeah, yeah, yeah.
29:16 - And then Henry out in the audience also says, "Hey Henry," it says, "It also, this doing things so quickly,
29:23 "it encourages good environment usage "because if doing things the right way
29:26 "is just as easy and as fast as doing it the wrong way, "you might as well do it the right way."
29:29 - That's a nice thought.
29:30 That's a nice thought.
29:31 - Yeah, it is.
29:32 - Yeah, I mean, I think there's, yeah, there are certain things though where like we aren't any faster
29:39 and I'm interested in thinking about like those and what we can do about them.
29:44 Like a common one or the most obvious one is in Python sometimes when you install a dependency,
29:51 you might have to build it from source.
29:54 And in Python, you often are installing things like NumPy, which have include some native code.
30:01 And so actually turning that into something that your system can run is kind of expensive.
30:06 And you typically don't have to think about this with NumPy because they ship what are called wheels,
30:11 which are kind of like these pre-compiled artifacts.
30:15 But not all packages ship wheels.
30:19 You could be on a platform that doesn't have a wheel for a variety of reasons.
30:22 You might get the raw NumPy source code and then have to, you get the raw NumPy source code
30:30 and then have to compile it down into a build distribution.
30:33 And like for us, if we get into that situation, it's like not gonna be any faster
30:38 because like we still have to build the thing from source.
30:41 Like just like that.
30:42 - That's the slowest part of the whole process.
30:44 - Yeah, and so there's like some, you know, there are some cases and some bottlenecks
30:48 where like it's, I'm kind of thinking about how could we do even better there?
30:52 And there are actually things that are changing in the standards that have made this a little easier.
30:55 Like there's this new thing called metadata 2.2.
30:58 It sounds cool, I know.
30:59 It basically lets you like read the metadata.
31:03 - You like metadata 2.1.
31:05 - Yeah, if you, yeah, I'm on, yeah, we're actually on 2.3 now.
31:09 - I just get it.
31:12 - But the point of that is like, it's a standard that makes it so you don't have to build the thing as often.
31:19 Like if you just wanna know the metadata of NumPy, for example, you may no longer need to build it
31:24 and before you did.
31:25 And so the standards are moving in a helpful direction here, but I just thought I'd call it out
31:29 because like the source distribution, there are cases where it won't be faster
31:33 and I'm pretty interested in those, but people should know that they also exist.
31:38 - There's also, it's not just time, there's also security issues around that, right?
31:43 If things are still based on building source from source and then running the setup py to see what the metadata is,
31:51 it's both slow and also potentially running arbitrary code just to install a thing, which can make you,
31:56 I mean, I don't know, rarely has anything gone wrong with just installing and running arbitrary code
32:01 off the internet, but sometimes it could go wrong.
32:03 - Yeah, it would be nice to get to a world where that's not required or at least for dependency resolution
32:11 and like the standards are moving in that direction.
32:14 - Yeah, exactly.
32:14 I mean, you might, if you're gonna use it, you're gonna have to get it, but if you just wanna know,
32:17 well, what versions do I need to put these two things together?
32:20 You shouldn't have to do that.
32:21 - Yeah, exactly.
32:22 Because today for NumPy, for example, if you didn't have a wheel, you would have to run some arbitrary code
32:27 to ask it for its dependencies.
32:29 - Yeah, exactly.
32:30 Well, let's talk about some of the usages here.
32:32 Let's see some more interesting comments in the chat.
32:35 We'll get back to them.
32:36 First of all, is it like Highlander, the movie, should there just be one?
32:42 Is this, is UPI a thing that I put into, say my requirements file if I wanna use it
32:47 or do I install it just once for my machine?
32:50 Like what's the scale?
32:51 - Yeah, so there's a lot of different ways.
32:54 You can, there's a lot of different ways to install it.
32:56 You definitely can install it into a virtual environment.
32:59 My general recommendation would be to install it on your machine once, because an interesting thing about UV
33:06 is you don't need Python to install it.
33:10 And it doesn't have, you need to have Python on your machine because we need to be able to, for example,
33:16 build source distributions or know where to install the thing, right?
33:19 We have to install into a virtual environment somewhere.
33:22 And so you have to have Python installed on your machine, but UV does not depend on Python.
33:28 So like it can install into arbitrary virtual environments or into arbitrary other Python interpreters.
33:34 So that's why we generally recommend using like the, these standalone installers that we have at the top
33:40 of the snippet on the screen.
33:42 They're like the curl and the PowerShell invocations.
33:45 Those will install a binary, a single binary on your machine that's UV.
33:51 And from there you can use UV to install into virtual environments that it creates,
33:57 to install into your system Python, to do whatever.
34:01 So like I would say most people, based on the statistics, based on our download statistics,
34:06 most people still install UV with pip, which makes sense, which is not that surprising to me.
34:11 But I would generally recommend having like one UV install on your machine.
34:16 Although if you do install into a virtual environment, like that's also totally fine.
34:19 Like nothing's gonna go wrong.
34:21 It's just not completely necessary because a single UV can already install
34:25 into that virtual environment.
34:26 - Right.
34:27 You're never going to import UV.
34:29 - No. - I mean, you might, but in general, people are not going to.
34:33 - I think you can.
34:34 I'm trying to think what would happen.
34:36 (laughs)
34:38 - It's not like, like things like pytest and other things.
34:42 A lot of times there could be just one of those, but then you wanna use fixtures
34:47 and you need to import something out.
34:49 So then it really needs to be in the virtual environment and accessible like a library.
34:52 But this is just something you run maybe even before your codes, before your virtual environment exists, right?
34:57 Like it really kind of does ideally exist outside it, I think.
35:02 - Yeah, ideally it exists outside of it.
35:03 And there are some cases where you'd wanna install it within the virtual environment,
35:06 but ideally it exists outside of it.
35:07 The other thing that's nice about using the standalone installers, like at the top here is,
35:13 soon we're gonna ship like a self update command.
35:16 So you can do like UV self update and it will update UV to the latest version.
35:20 And we can't really support that if you install it with a different package manager
35:24 like pip or Brew.
35:25 Those have their own upgrade commands obviously, but like if you install it with our installer,
35:30 then like we can control the upgrades and stuff like that and provide some other features.
35:36 So that's generally what we recommend, but obviously we're always gonna support
35:39 like installing with pip and stuff too.
35:41 - Yeah, I'm all about PipX these days.
35:44 I really like--
35:45 - Yeah, we're PipX, that's mine.
35:47 - Yeah, yeah, PipX really, you can just say up, kind of like Brew, you can say upgrade all my Python CLI tools,
35:54 PipX upgrade all.
35:56 Basically I find ruff and UV is just, you guys are moving super fast and there's frequently an update.
36:03 - There are often updates, yeah.
36:05 Yeah, and then the UV interface, like it's meant to be pretty familiar to,
36:11 or it's meant to be, I guess, hopefully very familiar to people who have used,
36:16 who are already using pip and other tools.
36:18 And so like UVVM creates a virtual environment.
36:22 And then there's, we have this sort of pip sub command.
36:27 So like UVPip install Flask, and that doesn't call or use pip in any way.
36:33 We're just using pip here to convey what the interface looks like.
36:38 And part of the motivation there is at some point in the future, we probably wanna add a new interface to UV
36:46 that's a little bit more high level.
36:50 So you could think of something like Poetry, where they have like Poetry install,
36:55 they have this sort of higher level interface for interfacing with packages.
37:00 We wanna do something like that.
37:02 And so that's why we left the top level of the interface clear, because we might kind of like integrate and,
37:10 sorry, innovate and like ship a bunch of stuff that would otherwise break this interface.
37:14 So like by putting this stuff under Pip, we basically created this like isolated space
37:19 where we can make sure that those commands like keep working no matter what we choose to change
37:23 in the future.
37:24 And it's very similar to Pip's interface, right?
37:27 It's like pip install, then it could be a package name.
37:29 It could be a dash R requirements file.
37:32 We support editable installs.
37:34 We support like URL dependencies, get dependencies, all that kind of stuff.
37:39 - Right, all the stuff you might normally do, pip install something for the most part, that's the same.
37:44 - Yep, yeah, exactly.
37:45 And we support a lot of the same flags too that like pip supports.
37:48 So like --index URL, -- extra index URL, like --no binary, like all that stuff.
37:54 Like we've put a lot of, we don't support every flag, but we've put a lot of effort into supporting a lot of them.
38:00 And we've added more over time.
38:01 Like now we support like --no build isolation and stuff like that,
38:05 that maybe most listeners have never even had to look at, but like, yeah, these things matter
38:10 in some circumstances.
38:12 And so like over time, our goal is to add like more of the interface.
38:15 But, you know, I would say for common use cases, I would expect that it just works.
38:22 Like just adding UV up front, like it should just work.
38:26 Now as you become more complex, it won't and you'll run into some.
38:30 We have a whole document of like subtle ways that we deviate some are intentional,
38:35 some I consider bugs, right?
38:36 Like some we want to fix over time.
38:38 But the intention is that for most people, we want it to just work.
38:41 - Once we fix the first round of bugs following the release, of course.
38:44 - Yeah, yeah, sure.
38:46 So you've got a UV, VENV, VIMP for creating a virtual environment.
38:51 And it has a lot of the flags that Python dash MVNV would have where you can say, you know,
38:57 bring along pip or upgrade things or set the prompt name, that kind of stuff, right?
39:02 - Yeah, yeah, exactly.
39:03 Yep.
39:04 - Similar for UV pip and then stuff.
39:06 What I find I do for most of my work, at least if I'm not trying to teach or do a presentation
39:12 where people are like, what did you just do?
39:14 These all have kind of aliases, right?
39:15 Like UV pip install -r requirements on TXT is just PIR, pip install requirements, you know, things like that.
39:22 - Yeah, yeah, yeah.
39:23 - And so try to just take the common stuff and it doesn't matter if it's pip or UV really backing it
39:30 from my CLI ergonomics, right?
39:33 I'm just, I use my alias.
39:35 And if I want to change that, I just go and edit it.
39:38 And so for me, it was super easy to switch to adopt these things because I'm like,
39:43 I added my ZSH RC file once and now everything just, I just do the same stuff and it works,
39:49 but the new way, way faster.
39:51 - Yeah, and you know, the goal of like pip compatibility has been interesting because there are actually like
39:57 some things that we very intentionally want to do differently and like, I won't speak for the pip maintainers
40:03 like, but I think in some cases, there are probably things that they would do differently too
40:07 if they could.
40:08 - I think so too, yeah.
40:09 - Yeah, 'cause like PIP, I mean, PIP's number one, pip is extremely important and its number one goal is like,
40:16 it needs to be like robust, right?
40:19 It needs to keep working and it needs to be compatible and 'cause it's like, it's truly like the cornerstone
40:25 of like a lot of the Python ecosystem.
40:28 And so PIP, it's very, it's harder for them to change things especially in a breaking way.
40:32 And they have to be really thoughtful and do that over a long period of time.
40:36 And so we're in kind of a privileged position, honestly, because we come in with a new tool,
40:41 we can actually do a bunch of, choose to do things differently.
40:44 And some people get upset about it obviously, 'cause they're like, this isn't exactly how pip does it.
40:49 I'm trying to hold firm on some of those things and also be open-minded on others, right?
40:53 But like, you know, like one thing that we do that's different, that's, I guess maybe it's not evident
40:59 from this screen exactly, or I guess it sort of is.
41:01 So when you do UVVM, we default the name .vm.
41:05 So like, if you don't provide a name, we just default to .vm.
41:09 And there was a PEP to make that a standard that got pulled back, but like,
41:14 it's not like we're trying to make it a standard, but I just think it's a good default.
41:17 Like we want to abstract away some of this stuff.
41:18 And so you can just like have a virtual, you can obviously pass a name if you want,
41:22 but we default to .vm.
41:23 That's different from other tools.
41:24 And then, you know, the other thing is when you do UVPIP install, by default we require a virtual environment.
41:31 And so if you do UVPIP install Flask and there's no virtual environment,
41:36 like we'll throw, we'll error.
41:38 And it doesn't have to be active.
41:40 We'll look for it in the current directory, even if it's not active.
41:42 So like, if you do UVVM, then UVPIP install Flask, like it will work.
41:46 And in my opinion, it will do the intuitive thing, which is it will install it into the environment
41:50 in the current directory.
41:51 So it's like, it's trying to provide-
41:52 - It'll traverse up?
41:53 Like if I'm a little farther down, it'll go up and say, "Oh, just, oh, that's amazing."
41:58 - Exactly.
41:59 So it'll find the virtual environment in the current directory or any parent directory.
42:02 So like, for me, that's just like a nice default workflow that encourages virtual environments
42:10 and like doesn't get in your way about it.
42:11 And we do have a flag for installing outside virtual environments, but the difference is in UV, you have to opt in
42:17 if you want to do something like install into the system Python.
42:21 The virtual environment, it's a very virtual environment first while abstracting away a lot of the details
42:25 of virtual environments.
42:27 So, you know, there are things like that where we made intentional decisions.
42:30 - Yeah. - In my opinion, yeah.
42:32 - Yeah.
42:33 - Yeah.
42:34 And I think, and it's nice because we can start with that behavior and, you know, we're in a privileged position
42:40 'cause we can start with different defaults.
42:42 - Yeah, for sure.
42:43 So if I do, excuse me, if I do a UV, VNV for a virtual environment, then maybe I UV pip install something,
42:54 but then I forget and I pip install something else.
42:58 Does it break?
42:59 Is it okay?
43:00 - As in the third time there's no UV?
43:02 - Well, yeah, exactly.
43:03 Like, so I'm in UV pip install something, UV pip install that.
43:07 And I was, oh, I forgot this thing.
43:08 I was pip install.
43:09 Oh, I forgot the UV.
43:11 To the state-- - No, it shouldn't break.
43:13 Assuming, so let's say you activate the virtual environment.
43:16 - Yeah, yeah, it's already activated.
43:17 - Okay, cool.
43:18 So you do UV VM, you activate the virtual environment, you do UV pip install flask,
43:22 and then you do pip install black or whatever.
43:24 - Yeah, something, yeah.
43:25 - That should work just fine because like the thing that we ultimately create
43:30 in the virtual environment, like that's all based on standards.
43:33 So like the stuff that we do in the virtual environment to install packages,
43:37 it should look like roughly indistinguishable from what pip would do.
43:41 And it's totally interoperable with pip.
43:43 So like similarly, if you did pip install and then like pip install flask
43:47 and then UV pip uninstall flask, like that would work correctly.
43:51 Like pip would install flask and we would remove it because everything that pip and UV are doing
43:55 in the virtual environment is based on standards.
43:58 So the way that we add and remove packages, all that kind of stuff, it should be totally interoperable with other tools.
44:04 - Okay, cool.
44:05 PyPI is pretty good at having analytics around what packages are being downloaded,
44:10 what's popular, what platforms.
44:13 Do you do anything like send a user agent or something so that people could answer the question
44:18 or how many people are using straight pip and how many people are using UV in a year?
44:23 - Yeah, we sent a UV user agent and it's right now it's just UV in the UV version.
44:29 There's an open issue in the repo from Pradyan who works on pip that outlines all this stuff
44:37 that pip includes in its own user agent, which we wanna add, which is pretty interesting.
44:43 I actually didn't know this.
44:44 So pip and its user agent includes a lot of things about the current Python platform,
44:50 data that they use in PyPI basically to inform decisions.
44:57 Oh, no one's using Py...
44:58 This is just, I don't think this is actually how it's used, but just an example.
45:01 Oh, no one's using Python 3.7 anymore.
45:03 Let's lower priority on that because no one's installing Python with Python 3.7.
45:08 And so we wanna add, we don't have that right now.
45:11 We're planning to add it.
45:12 But yeah, it will be interesting to see.
45:16 We can get statistics over time too on UV and pip and how common they are in different dimensions.
45:22 - Yeah.
45:22 One thing that would be kind of fun to have is, I'm not sure if it's at all interesting to you,
45:28 but to have some kind of cron job or background thing, if you just interact with UV,
45:34 if it kind of kicked off sort of a background process that did its thing.
45:37 But take the history of maybe the top 500 packages plus the ones you've used
45:43 and just kind of keep a cache up to date on your system.
45:46 So you're on an airplane or you're in a coffee shop or for some reason, the internet's not great.
45:51 Like it's kind of pre-filled the cache and everything's there.
45:55 And I kind of, that might be fun.
45:59 - Yeah, we do have a --offline flag, which will like, it forbids network requests obviously,
46:05 but it, so like it'll try and do the full install without accessing the network.
46:10 - Yeah, that's cool.
46:10 - It would be cool to pre-fill the cache.
46:12 - Yeah, but it's just like, you know, if you're a UV user and you sit down on your computer
46:16 and for some reason the internet's out, I'm at a conference, I'm doing a talk
46:19 and it's got the dreaded terrible conference wifi.
46:21 It's not the end of your demo.
46:22 It's just like, yeah, see how fast this is.
46:24 It's amazing.
46:25 - Yeah, yeah.
46:26 Yeah, it was actually, it's actually funny 'cause like the benchmarking, like when we do benchmarks,
46:31 like benchmarks can just vary so dramatically based on like internet connectivity, right?
46:36 Like that's often, that is often the bottleneck.
46:38 I mean, it's not, it's clearly not always the bottleneck because we're able to be faster than other tools.
46:44 So like if it was always the bottleneck, I don't think that wouldn't really be true,
46:47 but it matters a lot.
46:49 And so sometimes I'll throw on, on macOS, they have a tool called network link conditioner.
46:54 So you can actually force-
46:56 - Drag your network out.
46:58 - Yeah, you can force it down.
46:59 And the categories are like, it's not literally called like bad mobile phone
47:04 or something, but it's, that's like basically what it is.
47:06 Yeah, it's like, it's like, it's like very lossy edge network.
47:09 Like those are like the pre-built category.
47:11 It's pretty funny, but like it is actually, that's a very helpful thing for benchmarking.
47:15 - Yeah.
47:15 - And sometimes actually, if you have a really good network connection, sometimes it's actually helpful to set that anyway
47:20 to a pretty good level, because then at least it will be like very consistent
47:25 across your executions.
47:27 Anyway, it's something I've learned over time.
47:29 - Yeah, that is super interesting.
47:31 So one of the things I think is interesting to consider here is obviously this is way faster.
47:37 I saw some of the announcements and some of the discussion around the announcements
47:42 and the people were really surprised how fast this is.
47:45 And I think, I don't think Rust is the full answer.
47:48 You mean, you tell me if I'm wrong, but like one part, obviously making the code run ultra fast,
47:53 that is an important part of it.
47:55 But it also seems like you all have rethought some of the internal algorithms and some of the caching
48:01 and some of the ways things work, maybe with a fresh take on it, or you're not constrained by the way it's been done
48:06 for many, many years.
48:07 So what elements are at play to make it as fast as it is?
48:12 Is it just Rust or is it something else?
48:14 - So Rust is important, but like the way I typically talk about, like frame it is that Rust is kind of like an enabler
48:21 to writing really fast programs.
48:23 Like it lets you, it forces you slash lets you care, it forces you to slash lets you care about certain things
48:31 that matter a lot for performance that like in Python, you just act, there's actually just no way
48:35 to care about them.
48:37 Like I'm talking specifically here about like memory allocation, like in Python that all just kind of happens.
48:42 In Rust, you're forced to think about, am I gonna allocate memory here or not?
48:45 And like, when is it gonna be deallocated and all that kind of stuff.
48:49 And so that unlocks the ability to care and like be really careful in how you manage it.
48:54 And so Rust is like a really important, Rust is an important part of the success story here,
48:59 but I think it's like really, I think it would be really like very incorrect to say
49:04 that it's like all about Rust and it's not a Rust versus Python thing.
49:08 Like-- - Right.
49:09 Like if we could just recompile pip with--
49:11 (laughing)
49:13 - Yeah, so if you took--
49:14 - With a Cython or something and boom, it would just be, no, it wouldn't be as big of a deal, right?
49:19 - If you took pip and just like rewrote it line by line as close as you could in Rust,
49:23 like it would probably be faster than Pip, but it would not be nearly as fast as UV.
49:28 Like we just do a lot of things differently.
49:31 And part of like, I guess evidence for this too, is like throughout the development of UV,
49:36 there were like multiple pull requests that sped up like UV as a whole by like 30 to 50%.
49:41 So what does that say?
49:42 That says that like there's lots of different, those were all Rust programs, right?
49:46 So like we were able to write the same Rust program many times, optimizing it more and more and more.
49:52 - Right.
49:53 - And so there's like so much engineering that went into making it fast.
49:57 Some of it's like how the cache is designed.
49:59 That was like a really important piece.
50:01 And that's actually something that like pip could also do.
50:04 And I think like it's possible a good outcome here actually is that like pip is able to take some of these changes
50:11 and incorporate them over time.
50:13 And we are kind of the Guinea pig for that.
50:17 Like we're gonna kind of change user expectations a little bit about how the cache is set up.
50:21 Like we're gonna run into bugs about platform compatibility.
50:26 Like we're gonna run into bugs based on this cache design, right?
50:29 And like hopefully that could at some point help inform pip if they choose to redesign their cache this way.
50:34 The cache design is really big thing.
50:35 And then just a lot of like profiling the program, figuring out what the bottleneck is,
50:42 and then like solving the bottleneck and just like really intense engineering work
50:46 that was not me, but it was like other people on the team to optimize some of that.
50:49 Like a good example is, it's okay, it sounds silly, but like we found that a bottleneck
50:55 when all the data is cached and you're trying to do a resolution.
50:57 So there's no network requests, everything's local.
51:00 One of the bottlenecks that we kept running into was parsing and comparing versions, version specifiers.
51:07 So like in Python, when you have a requirements file, you have like FastAPI is greater than version one
51:14 or whatever.
51:15 And then in the FastAPI file, you have like FastAPI version 1.0.0, blah, blah, blah.
51:20 So like those, like parsing those, and then we were comparing those.
51:25 We were doing comparisons between version markers like so many times, because it was just a constant thing
51:32 in dependency resolution.
51:32 It's like, can I use this dependency?
51:34 Well, does it fit to this range?
51:36 - So Andrew Gallant from our team, like rewrote that parser and the version comparison specifier.
51:44 And it's like one of the most incredible pull requests I've ever seen.
51:47 Like it's like so interesting.
51:48 Like every commitment is like so interesting.
51:51 And he like optimized it so massively that it was like, he's basically representing the version in the end
51:56 by like a 64 bit, like a U64 integer.
52:01 And comparisons is just like compare the two integers.
52:03 And like, there was just so much engineering that went into it.
52:06 And it sped up the cache case by like 30%.
52:07 And so there's a lot of, there's just a lot of engineering that went into it.
52:12 And, you know, again, it's harder for pip to do some of those things 'cause the code bases,
52:18 they have a lot, they have actual users to support, right?
52:22 Like we were able to do this before we launched publicly, like we could break things,
52:26 like we can do things, you know, we can make massive changes to the code base
52:30 in short periods of time.
52:31 So, you know, we're in kind of a privileged position to be able to really optimize the performance like that.
52:36 But, you know, it's a big part culturally of what we wanted to do too, is like, we're gonna make this thing extremely fast.
52:42 - Yeah, I'm seeing also interesting secondary effects, you know, talks and not, not,
52:48 I guess talks, talking about using it, making it faster.
52:52 Just now I hear Henry says, "Build 1.1 is faster from looking at UV." And the next version will also add UV as an installer choice,
52:59 which is pretty impressive.
53:01 - Yeah, that's been a really cool, that's actually something I didn't really anticipate,
53:05 but I'm really glad has happened, which is that there's a little bit of like,
53:10 we ended up building something pretty modular.
53:12 And so there's been a little bit of, or a lot of like integrations with UV
53:17 that people have been building.
53:18 Like, like Bernat had the talks UV thing that was out like within a week, I think,
53:25 which was like use UV to power talks in different ways.
53:29 Yeah, Knox, I think supports it, build, pypi/build.
53:33 - Ah.
53:34 - You know, I've talked to the Hatch maintainer, you know, like he's pretty interested in making UV
53:41 like an optional backend for Hatch.
53:43 So like, that's really cool to me 'cause it's all just like magnifying the impact.
53:48 And again, I don't know how much of that I anticipated, but it's really cool to see that like,
53:55 you could plug it into these other tools and they can just like go much faster.
53:59 So I don't know, for me, that's been like, that's actually been like a big highlight
54:03 from the release, honestly, has been the reception from like other maintainers
54:06 of other tools who have been excited to integrate it in different ways.
54:09 'Cause it's just not, it just didn't happen.
54:12 Like ruff wasn't nearly as much of a fit for that kind of thing.
54:16 Like there just aren't as nearly, there are some, but it's just not as natural to have like integrations
54:20 with rough in that way.
54:22 But for UV, it makes a lot of sense and it's been really cool to see.
54:24 - Yeah, it's more, UV is more of a building block than rough is.
54:27 Ruff fits in editors and CI and stuff.
54:30 Yeah, okay.
54:31 - There were other tools, but yeah, it's mostly an end user thing and not a library, I think.
54:38 - Right, all right.
54:39 So a couple of interesting things out in the audience.
54:41 Let's knock them out.
54:42 Okay, so Tushar asks, and this is, I think, a big tension that's building in the Python packaging space
54:50 is do packaging tools use Python to do stuff?
54:54 Or do the packaging tools control the Python?
54:56 Who is controlling whom here?
54:59 And so Tushar asks, will UV also install Python sometime soon?
55:02 Can I just express, hey, I wanna use 3.12 on this in these dependencies?
55:07 - Yeah, we almost certainly wanna do this.
55:10 I don't think it will be, it won't be required.
55:13 Like you can still use your own Python, but we almost certainly want to add Python bootstrapping.
55:19 So like, that's another reason why the dream workflow is like you use the standalone UV installer
55:26 because then it's like, it will actually install Python for you too.
55:30 And so like the reason, so then it's like, you don't have to have Python on your machine basically
55:35 to start being productive with UV.
55:37 You can just bootstrap the environment for you.
55:39 And we can also do, you know, yeah, it would just be nice if you did, you know,
55:44 pip compile, like UV pip compile, --Python 3.13 or something.
55:50 And then we just like bootstrapped Python 3.13 and did the resolution on your machine.
55:54 Like that's kind of the workflow that we're trying to build towards.
55:56 - Yeah, since you're so UV centric as well, it could be UV, VNV, you know, --version.
56:02 - Yeah, a hundred percent.
56:03 - 3.12 or whatever.
56:04 - And then we bootstrap it, yeah.
56:05 - If you don't have, if you've got a cache, you just give it.
56:07 And if you don't, then you get it on the machine.
56:09 - Exactly.
56:10 - Yeah.
56:11 - Yeah, so we'll definitely do this.
56:13 Again, I do think it's important that it's not like required to use like the UV Pythons.
56:17 We actually kind of had to do like a minimal version of this for our CI and testing.
56:25 But it was a batch script and then I think it became a Python script, but eventually it would be like built into UV.
56:32 Yeah.
56:33 - Yeah, yeah.
56:34 I think that would be really.
56:34 - Yeah, I think it'll be super cool.
56:35 - Really quite awesome.
56:36 - Yeah, I think it will be too.
56:38 Let's see.
56:39 Tushar also says, loves that the --require VNV.
56:43 - Yep.
56:44 - As a thing.
56:45 He thinks it'll become the default and also points out for those who don't UV
56:49 that pip require virtual VNV as an environment flag is in your RC files.
56:53 It's pretty nice.
56:54 I need to do that just the other day.
56:55 - Yeah, you can.
56:56 - Oh, I spelled that to the wrong spot.
57:00 - Yeah, so pip can be configured to require virtual ends.
57:03 - Yes.
57:04 - Yeah, I do something weird.
57:05 I'm actually looking at my terminal behind our shared screen, our meeting here.
57:09 And my prompt says global VNV.
57:12 And so one of the things that I do is have a, just if I log it, if I open up my terminal,
57:16 it already has an activated virtual environment.
57:18 It's just for whatever.
57:20 - Oh, interesting.
57:20 To just avoid messing up your system Python.
57:22 - Just to avoid messing it up.
57:23 Or so I can have, I can just make that virtual environment the version of Python I want it to be,
57:28 even if it's not the system one in general that I want to set, you know, just like,
57:32 it's its own thing.
57:33 And so it wouldn't actually help me, but I still like that.
57:35 - That's smart.
57:36 Yeah, that's smart.
57:37 (laughs)
57:38 - Thanks.
57:39 - Yeah, I've learned a lot about like, oh my gosh.
57:42 I mean, I've learned a lot about packaging.
57:43 Like I didn't know like anything about packaging, you know, like six months ago.
57:48 I shouldn't, I should actually shouldn't admit that 'cause it's really bad for my credibility,
57:51 but like I've learned a lot about packaging and in the past like two weeks,
57:56 I've also learned a lot about like system Pythons, like how Python is installed
58:02 and like how on like older versions of like Debian, like Python, they do like a lot of customization to Python
58:09 that makes it like really different from like, and I learned like way more about this
58:13 than I ever thought I would.
58:15 - I think it's fine to say that.
58:16 - I'm out on system Pythons, but we do support them.
58:18 - Yeah, awesome.
58:19 You know, someone asked me like, no, Michael, you must know all of the standard library.
58:24 I'm like, what are you crazy?
58:25 No.
58:26 - Yeah.
58:27 - Why would I want to know everything?
58:28 Yes, exactly.
58:29 And I think it's the same thing about packaging.
58:31 There's like so many edge cases.
58:33 If you never interact with an edge case and you don't care about that edge case,
58:36 why would you take the week or whatever to study it?
58:38 Like it's just, it's irrelevant to you until you need it.
58:41 And now you've dove in head first here.
58:44 So then you're in the deep end with it.
58:47 - We spent so much time.
58:49 I shouldn't even bring this up, but we did, okay, when we were, whatever,
58:53 I won't tell the whole story 'cause I need to not, but like we did consider like lots of different names
58:58 for this tool and multiple times we considered a name and then it turned out to be a standard library module
59:03 that none of us had ever used.
59:05 Like we wanted to use WAVE, W-A-V-E, but that's a standard library module.
59:10 Yeah, yeah.
59:11 I was like, oh, I had no idea.
59:12 - Is that for working with WAVE audio files?
59:14 Probably it is.
59:15 - Yeah, like WAV files, yeah.
59:17 - Yeah, interesting.
59:18 Yeah, there's a bunch of stuff.
59:19 There's a whole demo reason removing certain things that like, you know, I know it's like a library,
59:25 but some of these things I had never seen.
59:28 - Yeah, well, it's naming tools and packages is a whole special deal.
59:33 And we have half a million packages in PyPI.
59:36 And so how are you gonna not conflict with that?
59:38 Have an interesting name.
59:39 That's not for, I'm for typo squatting.
59:42 - Yeah, exactly.
59:43 - Hard, it's a hard problem.
59:44 - Yeah, I don't even get me started on name stuff.
59:46 Someone actually donated this name to us, which is very kind of them.
59:49 - Oh, that's actually very cool.
59:51 Very cool.
59:52 All right, one other thing I do wanna talk about here, Kanishka says, asks about, you know,
59:58 is there a future where Rye, R-Y-E, and UV go hand in hand, also great work,
01:00:03 but maybe just talk a bit about Rye.
01:00:05 That was by Armin Roenicker, and it kind of had a similar zen as UV, but really different.
01:00:10 - Yeah, so we, yeah, so we're taking over like maintainership of Rye, and we've just been like,
01:00:19 I think I started talking to Armin, like right after Rye got released, which was PyCon last year,
01:00:25 I think it was during PyCon it got released.
01:00:27 And we talked like shortly after, and we just found that like, we were trying to do a lot of the,
01:00:32 we were trying to solve a lot of the same problems, and we had like very similar vision
01:00:35 for what we wanted packaging to be.
01:00:37 But like, we were coming at it from very different angles, like Rye kind of came at it from,
01:00:42 let's solve the Python bootstrapping problem.
01:00:44 So we're gonna ship a Rust tool.
01:00:45 - It's like it's main focus, yeah.
01:00:46 - Yeah, exactly.
01:00:47 And then internally, it was actually using like pip tools, and pip to do installs and resolutions.
01:00:54 And then the thing that, I think the thing that Armin came to realize was like,
01:00:58 if you wanna fulfill this whole vision, you kind of need to like reinvent a lot of those internals.
01:01:03 And meanwhile, like we were building UV, which was like basically those internals.
01:01:07 And I was like, we're gonna put a lot of effort into like building this packaging stack.
01:01:13 And so we kind of found that like, it was just a really, we were trying to get to the same place.
01:01:18 And we were putting in a lot of the engineering investment on building a lot of kind of building blocks.
01:01:23 And we want UV to evolve into something that could like fully replace Rye.
01:01:28 So we want it to evolve in that direction.
01:01:31 And in the meantime, like we're gonna keep maintaining Rye and kind of using it as like a little bit of a test bed
01:01:38 for like experimental things, like Armin added like pytest support to it, for example.
01:01:42 So we're like, we're kind of playing with like, that's meant to be more of an experimental test bed
01:01:47 for like the future that we wanna achieve.
01:01:49 And over time, we're gonna kind of evolve UV up to the point that hopefully it can fully replace it.
01:01:53 And then we can provide a clear migration path for it.
01:01:56 So we're gonna keep maintaining it.
01:01:58 It is our intention for UV to like, to supplant it at some point in the future,
01:02:04 but it'll take us like time for it to get there and be able to do all the things.
01:02:08 But the visions were just so similar that it seemed like it made a lot of sense
01:02:11 to try and consolidate and kind of team up on it.
01:02:14 - Yeah, they do seem pretty similar.
01:02:16 And I can see the direction that you're going in it.
01:02:19 It's gonna make them more similar.
01:02:21 - Yeah, I know it'll take time.
01:02:22 And like, you know, this release of UV is like, it really is like the first release, you know?
01:02:26 It's like, I kind of use some of this stuff as like pretty low level.
01:02:30 Like we wanna build something that feels higher level and more automatic in the future.
01:02:35 But these are kind of like the ability to install and uninstall and resolve packages.
01:02:40 And these were like the fundamental things we needed and need for anything we were gonna do.
01:02:44 And so this goal was really, let's take those and let's put them in a form
01:02:48 that's like immediately useful to people.
01:02:50 - Yeah, for sure.
01:02:51 One more Rye question, then I have other questions.
01:02:54 So UV will replace Rye.
01:02:56 Do you recommend using Rye or UV or what's that side of the story, right?
01:03:01 - Yeah, yeah, yeah.
01:03:02 It kind of depends on what you're doing.
01:03:04 So like Rye uses UV under the hood.
01:03:07 So like Rye uses UV for resolution and installation.
01:03:11 So if you're using Rye, you're using UV.
01:03:13 I like, I say, I consider UV to be like, especially if you're like a company or something,
01:03:19 like I would say UV is production ready for you.
01:03:23 Rye, you're buying into a little bit more of something that's a little bit more experimental.
01:03:29 Like I think Rye is a good fit for like professional projects, hobby projects,
01:03:32 libraries, smaller projects.
01:03:33 I don't know that I would, like you're just buying into more change, I think.
01:03:40 - Yeah.
01:03:41 - And so if you're already--
01:03:41 - So if you're a modern repo, that's got a million lines of code and 110 people on it.
01:03:46 - Yeah, you can certainly try it, but you should know that you're buying
01:03:49 into something experimental is the way I'd put it.
01:03:51 Whereas UV, like you could also view UV as experimental if you want.
01:03:55 Like it's very new, right?
01:03:56 Like we've, we're like when we launched, we had, I mean, I think having issues is actually good
01:04:00 'cause it means people are using your project, but we had like hundreds of issues
01:04:03 and we closed and we closed, we've closed like hundreds and hundreds of issues
01:04:07 since we launched.
01:04:08 - Yeah, you guys have been super, yeah, you've been super responsive on it.
01:04:10 Like you and I've had some exchanges there.
01:04:13 - Yeah, we did.
01:04:14 - And yeah, that's some nice changes I saw going on, but like I said, almost every day--
01:04:19 - It's just getting like way better.
01:04:20 - It's great.
01:04:21 - Yeah, and it's just getting way, way better.
01:04:22 Like that's the thing about developing in private is like, like we just, once we released it,
01:04:27 we finally, we actually had users who could use it and tell us all the things we missed,
01:04:30 tell us all the things we didn't think about.
01:04:31 It's just like every week getting way better.
01:04:33 So like it's getting more and more stable and like I would use it in production for my stuff,
01:04:38 for sure, and I recommend it for production.
01:04:41 But like Rye is just a little bit of a different story.
01:04:44 I think with Rye, you know, it's not like we're gonna shut it down tomorrow
01:04:48 or anything like that.
01:04:49 Like it's gonna be, it's gonna continue to be supported for sure.
01:04:52 But you are, and I think it's branded this way, which is you're are kind of buying
01:04:57 into a little bit of an experimental tool.
01:04:59 - Yeah, also a bit of a workflow.
01:05:01 - Yeah, it's a very opinionated workflow.
01:05:03 - Yeah. - Yeah.
01:05:04 Whereas you'd use more design to kind of slot into existing workflows.
01:05:07 - Sure, it's a little more foundational.
01:05:10 Speaking of which, I really like that, you know, so many of these tools have their own,
01:05:16 their complete own way.
01:05:17 Like I know you're gonna do that, but we're gonna start up our shell and then you're gonna run these three commands
01:05:22 and then we're gonna have our own lock file and we have our own things.
01:05:24 And it's amazing if you drink the Kool-Aid, if you go all in on the tool.
01:05:29 But if you don't, then it's like, okay, well, what is this thing even doing?
01:05:33 It's more in my way than it's helping me, you know, and so on.
01:05:36 So the fact that a lot of this is kind of baking in the pip-tools way of,
01:05:42 there's gonna be this external tool that can manage some of your stuff for you,
01:05:46 but it's not prescribing a workflow, 100% props for that, love it.
01:05:50 - Thanks, yeah, I wanted to build something that, again, I use the word like modular a lot
01:05:55 and I think it can mean different things, but like, Ruff was kind of like this too.
01:05:59 Like in Ruff, you can use it as like just a linter or like just a formatter or both.
01:06:03 And like with UV, like you could use UV like just to create virtual environments
01:06:07 or just to do dependency resolution, but use pip for your installer or something.
01:06:12 Like it's designed to be kind of flexible in how you choose to use it.
01:06:17 And I wanna maintain that, you know, I think we'll start to introduce more opinionated workflows,
01:06:23 but I think that we'll continue to provide this kind of pick and choose model as well.
01:06:29 - Yeah, yeah, I think it's great.
01:06:31 It lines right up with the way I do things.
01:06:33 And also I really like it as both someone who might do presentations either at a conference
01:06:38 or in a course or teaching, because you're not putting, you know, the whole virtual environment stuff
01:06:43 is already such a kind of a large barrier that comes a little early in people's learning path, right?
01:06:49 They're like, I wanna run Python, I wanna run this thing.
01:06:51 Whoa, you don't just install this, you don't just use it.
01:06:55 We're gonna talk about virtual environments.
01:06:56 Like, I don't care about those, I just wanna run it.
01:06:58 Like, but you're gonna need to install something.
01:06:59 So here we go.
01:07:00 Right, adding more workflow and more specific ways of working there, I think while trying to help a lot of times
01:07:06 they end up just adding more friction at the start.
01:07:09 - Yeah, yeah.
01:07:10 And like, I guess my philosophy there is like, I want us to like embrace virtual environments.
01:07:17 I think Rye has this philosophy too, which is like Rye does use virtual environments.
01:07:20 And like virtual environments actually have a lot of, there's a lot of benefits to embracing them.
01:07:24 Like all the editors and such, they're all built around virtual, they all are all built around virtual environment detection
01:07:29 and stuff like that.
01:07:31 But I wanted to feel, I wanted to feel a little, honestly, like it has a really bad reputation,
01:07:36 but I wanted to feel more like node modules, you know?
01:07:38 - Yeah, I agree.
01:07:40 - It just kind of works in your, it just kind of sits in your project and your project just does the right thing.
01:07:44 And I know people make fun of node modules usually for being big, but like, but that's the developer experience I want,
01:07:50 which is you don't think of the virtual environment as this weird other thing.
01:07:53 It's just kind of like the project environment and it just kind of works.
01:07:56 And I think, I think you get that by not like fielding people from it, but abstracting some of it away
01:08:02 for people that don't need to think about it.
01:08:04 - Yeah, there was a, there was an amazing, it's not a joke, but it's, I guess,
01:08:09 something that's a prank that somebody came up with.
01:08:14 Here, I'll put it on the screen.
01:08:15 It's called "When Everything Becomes Too Much," the NPM package chaos of 2024.
01:08:21 And I was just, as you were talking about node modules, this is more of a- - Oh my gosh.
01:08:24 I haven't seen this.
01:08:25 - It's amazing.
01:08:26 So it's more of a statement of like, well, how super interdependent or how many combinatorial or transitive dependencies
01:08:35 does a couple of NPM things have?
01:08:37 Like, for example, I used Tailwind, but there was maybe 50 things in my node module
01:08:43 for just using Tailwind in my project, right?
01:08:45 So anyway, this one is, an NPM user named PatrickJS launched a troll campaign
01:08:51 where a package called everything, it depended on every other NPM package.
01:08:55 So if you, you know, NPM install everything, they literally try to download the repository.
01:09:00 - Yeah, that's kind of amazing.
01:09:03 Wow. - I know.
01:09:04 It's devious, but it's also kind of like, okay, that's something else.
01:09:09 - Yeah, and Python and dependency trees tend to be much, like, shorter, I guess, and like smaller.
01:09:15 Like, you tend to have way fewer dependencies.
01:09:18 They are sometimes like heavier, I guess, 'cause like in Python, it's very common to have lots of native code.
01:09:24 And like, I don't know, like PyTorch, like the PyTorch wheels that you download
01:09:30 when they're zipped are like between 100 and 200 megabytes.
01:09:34 - Wow, okay. - And like, yeah, yeah.
01:09:36 Like all the ML stuff and all the native stuff, like those are like big,
01:09:40 but the number of dependencies tends to be a lot smaller.
01:09:43 - Yeah, I totally agree.
01:09:44 - It's also very common to ship like foundational packages with like no dependencies or very few dependencies,
01:09:49 which is very hard to do in JavaScript.
01:09:52 - Yeah, it is.
01:09:53 It definitely is.
01:09:55 All right, I think we're getting short on time here.
01:09:57 I think I probably should let you go back and knock out another release of UV.
01:10:01 - I do have a new release today.
01:10:02 Okay, thank you. - Awesome.
01:10:03 (laughing)
01:10:04 So Tony, all the audience has been using UV in production for a couple of weeks now.
01:10:08 Also, seems very excited about it.
01:10:10 And also, I have two.
01:10:12 It's an absolute delight.
01:10:14 It hasn't, I know there were certain, yeah, I know there are certain things
01:10:17 that it didn't do like right away, but then it came out and you added them quickly.
01:10:23 I know there was some criticism for you all for developing this in private and then releasing it.
01:10:29 And I just wanna say like, you know, thanks for doing that.
01:10:31 And what's the alternative?
01:10:32 You start with just a blank GitHub repo and people start to say, well, you should do this.
01:10:37 You should be doing that.
01:10:38 Like, we have a vision.
01:10:39 Let us just like get it a little structure in place and then we'll open source it.
01:10:42 Like give us a month, you know?
01:10:45 So I don't know.
01:10:46 I think it's excellent work you're doing.
01:10:48 - I appreciate it.
01:10:49 I appreciate it.
01:10:50 Yeah, yeah.
01:10:51 You know, like I said at the start, it's different this time because anything we release,
01:10:55 like, you know.
01:10:57 - You can work on a ruff for a month and nobody cares until it starts to catch some traction.
01:11:01 Right?
01:11:02 But this is the instant that it hits.
01:11:03 - Yeah, we knew people would at least look at it and at least try it.
01:11:07 And I think, you know, we wanted to make sure that whatever we released, first of all, was good.
01:11:11 And second of all, that we were ready to maintain it.
01:11:13 And I think with packaging too, it's like, there's just a lot of, it's just such a complex space
01:11:19 that like, I wanted to make sure that we had a lot of clarity in the messaging
01:11:23 around what the tool is and what it's not and like what we want it to be and what it isn't yet.
01:11:28 And so I'm really happy with how the launch went and I've really appreciated just all the excitement,
01:11:34 activity, engagement that we've had on the repo.
01:11:37 It's been like, I don't know.
01:11:39 I mean, honestly, it's been a lot of work.
01:11:41 But it's like really, really, no, but it's awesome.
01:11:45 It's like so energizing for me and for the team.
01:11:48 - And to see all the people picking it up and making it the foundation of their projects.
01:11:52 And yeah, it's really cool.
01:11:53 - Yeah, and it's cool.
01:11:54 You know, I guess another, like one other thing that's a little different this time is like,
01:11:58 I talk, I just talked to more people who work on Python tooling at companies now
01:12:02 than I did when I released Ruff, just 'cause over the course of the past year,
01:12:06 I've just met a lot of people and we've just talked about how they're using Ruff,
01:12:09 how they're not.
01:12:10 And so just hearing some of those stories too of how like companies are starting to use it
01:12:14 and like what the blockers are and like how much of a speed up it's providing
01:12:17 has been pretty cool to see too.
01:12:18 So yeah, I know I appreciate it though.
01:12:21 - Yeah, you're welcome.
01:12:21 All right, we'll leave with this final thought from Juan.
01:12:23 I installed 94 libraries in around two seconds.
01:12:25 Incredible. - That's great.
01:12:26 - All right.
01:12:27 (laughing)
01:12:29 All right, well, I'm excited to see where things go and you know, we'll maybe do a follow-up
01:12:32 when you've got some more of the ideas in place.
01:12:37 - Sounds great.
01:12:38 No, it's always a pleasure.
01:12:39 Thanks so much for having me on.
01:12:39 I really appreciate it.
01:12:40 - Yeah, thanks Charlie.
01:12:42 This has been another episode of Talk Python to Me.
01:12:46 Thank you to our sponsors.
01:12:47 Be sure to check out what they're offering.
01:12:48 It really helps support the show.
01:12:51 It's time to stop asking relational databases to do more than they were made for
01:12:55 and simplify complex data models with graphs.
01:12:59 Check out the sample FastAPI project and see what Neo4j, a native graph database can do for you.
01:13:05 Find out more at talkpython.fm/neo4j.
01:13:10 Want to level up your Python?
01:13:12 We have one of the largest catalogs of Python video courses over at Talk Python.
01:13:16 Our content ranges from true beginners to deeply advanced topics like memory and async.
01:13:21 And best of all, there's not a subscription in sight.
01:13:24 Check it out for yourself at training.talkpython.fm.
01:13:27 Be sure to subscribe to the show.
01:13:29 Open your favorite podcast app and search for Python.
01:13:32 We should be right at the top.
01:13:33 You can also find the iTunes feed at /itunes, the Google Play feed at /play,
01:13:38 and the direct RSS feed at /rss on talkpython.fm.
01:13:42 We're live streaming most of our recordings these days.
01:13:45 If you want to be part of the show and have your comments featured on the air,
01:13:48 be sure to subscribe to our YouTube channel at talkpython.fm/youtube.
01:13:53 This is your host, Michael Kennedy.
01:13:55 Thanks so much for listening.
01:13:56 I really appreciate it.
01:13:57 Now get out there and write some Python code.
01:14:00 (upbeat music)
01:14:18 Here's what's next!