WEBVTT

00:00:00.001 --> 00:00:05.480
Hey folks, for our final episode of 2022 here on Python Bytes, we're crossing the streams with my

00:00:05.480 --> 00:00:10.340
other show, Talk Python To Me. I present to you one of the more important episodes over there

00:00:10.340 --> 00:00:16.740
for the year, the release of Python 3.11 with its new features and 40% performance improvements.

00:00:16.740 --> 00:00:22.220
Thank you for listening to Python Bytes in 2022. Have a great holiday break,

00:00:22.220 --> 00:00:26.600
and Brian and I will see you next week. Here's that Python 3.11 episode.

00:00:28.980 --> 00:00:34.200
Python 3.11 is here. Keeping with the annual release cycle, the Python Core devs have released

00:00:34.200 --> 00:00:39.740
the latest version of Python, and this one is a big one. It has more friendly error messages and

00:00:39.740 --> 00:00:47.840
is massively faster than 3.10, being between 10 to 60% faster in general, which is a big deal for a

00:00:47.840 --> 00:00:53.580
year-over-year release of a 30-year-old platform. On this episode, we have Erit Katril, Pablo Galindo

00:00:53.580 --> 00:00:58.480
Sogato, Mark Shannon, and Brant Booker, all of whom participated in releasing Python this week.

00:00:58.480 --> 00:01:02.760
The hero on Talk Python to tell us all about that process and some of the highlight features.

00:01:02.760 --> 00:01:08.520
This is Talk Python To Me, episode 388, recorded October 28th, 2022.

00:01:21.700 --> 00:01:27.200
Welcome to Talk Python To Me, a weekly podcast on Python. This is your host, Michael Kennedy. Follow

00:01:27.200 --> 00:01:31.500
me on Twitter, where I'm @mkennedy, and keep up with the show and listen to past episodes at

00:01:31.500 --> 00:01:37.880
Talk Python.fm. And follow the show on Twitter via at Talk Python. We've started streaming most of our

00:01:37.880 --> 00:01:43.540
episodes live on YouTube. Subscribe to our YouTube channel over at talkpython.fm/youtube to

00:01:43.540 --> 00:01:47.000
get notified about upcoming shows and be part of that episode.

00:01:47.700 --> 00:01:51.940
Hey, everyone. Welcome to Talk Python To Me. It's great to have you all here. Erit,

00:01:51.940 --> 00:01:57.760
Brant, Pablo, and Mark. It's going to be super fun to speak with all of you about Python 3.11.

00:01:57.760 --> 00:02:02.100
Before we get into it, I guess, just real quickly, I know some of you have been on the show before,

00:02:02.100 --> 00:02:07.000
but not all of you. So let's just do a quick introduction about who you are and how you ended

00:02:07.000 --> 00:02:09.680
up here on the show. Erit, you want to start first?

00:02:09.680 --> 00:02:16.740
Yeah. Hi, I'm Erit, I'm a Python core dev. Earlier in the week, we streamed the release of Python 3.11.

00:02:16.740 --> 00:02:20.820
And on the back of that, Michael just invited us all here for chat.

00:02:20.820 --> 00:02:25.440
Fantastic. Yeah. That was a great live stream. And we'll talk about that for sure in a second.

00:02:25.440 --> 00:02:26.960
But Brant, welcome back.

00:02:26.960 --> 00:02:33.100
Hello. My name is Brant Bucher. I have been a core dev for like two years now. And I work with Mark and

00:02:33.100 --> 00:02:35.200
Erit on the Faster CPython team at Microsoft.

00:02:35.200 --> 00:02:35.680
Right on.

00:02:35.680 --> 00:02:37.500
And I was on the show like a month ago.

00:02:37.500 --> 00:02:41.460
Yeah, you were talking about the Faster Python stuff, which we'll touch on again.

00:02:41.460 --> 00:02:48.020
Hello. I'm Pablo Galindo. I'm the infamous release manager. I released Python 3.11. And you can

00:02:48.020 --> 00:02:54.260
redirect all your complaints to my email address. No, please don't do that. So I'm a cPython core dev.

00:02:54.260 --> 00:03:00.480
I'm also serving this year and the last year on the Python steering council. And I also release,

00:03:00.480 --> 00:03:06.100
I'm the release manager for Python 3.10 and 3.11, which is now the best version of Python. Download it

00:03:06.100 --> 00:03:10.340
today. Apart from that, I do a bunch of parser stuff. But now we are not talking about that.

00:03:10.340 --> 00:03:12.660
Yeah, fantastic. Well, welcome. Mark, welcome back.

00:03:12.660 --> 00:03:17.860
Hi there. I'm Mark Chan. I'm the tech lead of the Faster CPython team. I work with Erit and Brant.

00:03:17.860 --> 00:03:20.940
I've been a core dev for some number of years. I don't recall.

00:03:20.940 --> 00:03:27.120
You've been spending a couple of years working on this Faster CPython thing and very excited to see

00:03:27.120 --> 00:03:31.100
some of the fruits of those labors, you know, starting to show up and get in the hands of

00:03:31.100 --> 00:03:35.560
everyone with this release. Yeah, it's good to have the stuff out actually in public and in people's

00:03:35.560 --> 00:03:39.660
hands. It's really rewarding to know that stuff you're working on is actually used and used by a

00:03:39.660 --> 00:03:44.840
lot of people. Yeah, that is totally true. It's one thing to build software. I mean, just by itself,

00:03:44.840 --> 00:03:51.520
but it's fun. But all of you are working on code that touches so many people. Think about there's

00:03:51.520 --> 00:03:57.040
layers, right? One layer is how many people use Python? Many millions, millions. Does anyone know

00:03:57.040 --> 00:04:02.880
a reasonable estimate of this number? I think some, I don't remember who came with the number,

00:04:02.880 --> 00:04:07.100
but I think they were estimating like 6 million Python developers, something like that. I mean,

00:04:07.100 --> 00:04:14.480
probably is between zero and 10 million, let's say. Yeah, that's a massive impact, but, and also maybe

00:04:14.480 --> 00:04:19.440
nervousness about pushing code out to that group. But then, you know, those people will build software

00:04:19.440 --> 00:04:25.000
for others, right? If you're using Instagram or using YouTube or other things, right? It's also

00:04:25.000 --> 00:04:30.600
having massive knock-on effects there. So thanks for putting all this together. Thanks for improving the

00:04:30.600 --> 00:04:39.620
tools that we all get to use. So yeah, big news. The big news is that Python 3.11 is out. And as

00:04:39.620 --> 00:04:46.580
Iretz had said, you all live streamed that release. So here we're all together, we're having an awesome

00:04:46.580 --> 00:04:51.700
chat about the features and the, what people can do to take advantage of it and why they might care about

00:04:51.700 --> 00:04:57.300
new features and want to learn them. But there you did a little bit of that, but also Pablo, you actually

00:04:57.300 --> 00:05:04.820
step-by-step did the release of CPython mostly live, right? Yeah, I did. It was, except the boring

00:05:04.820 --> 00:05:11.300
parts. This is something that I started last year because apparently I didn't have enough

00:05:11.300 --> 00:05:16.900
things to worry and I decided to make my life even more difficult. I'm an expert on that. Quite

00:05:16.900 --> 00:05:21.860
proficient. I'm also an expert. I'm very bad at doing too many things and yeah. You could be a release

00:05:21.860 --> 00:05:28.980
manager. It's the only requirement. So yeah, the idea is that the kind of releasing Python is a process that

00:05:28.980 --> 00:05:33.300
is quite complicated. It's also quite boring. So it's not like, you know, you need to be,

00:05:34.020 --> 00:05:38.420
have a galaxy brain kind of thing to do it, but it's just a lot of steps and it's very easy to do

00:05:38.420 --> 00:05:45.060
it wrong. And it's very unglamorous. So I said, oh wow, I'm sure people really would like to see

00:05:45.060 --> 00:05:50.020
a very unglamorous process happening in life. And then I said, let's do it. And I asked around and I

00:05:50.020 --> 00:05:55.700
was surprised about how many people enjoy unglamorous processes. And then I did the release of Python 310

00:05:55.700 --> 00:06:01.300
beta 1, which turned out to be much funnier than I thought because we just broke GitHub. That happened live.

00:06:01.300 --> 00:06:07.860
Yes. Was that when you imported all the, you imported all the issues and did that migration or was that

00:06:07.860 --> 00:06:12.580
separate? You will think that that is a good candidate, but no, that was not the thing that broke GitHub.

00:06:12.580 --> 00:06:17.780
We renamed master to main on the CPython repo and the whole GitHub platform was down. What about that?

00:06:17.780 --> 00:06:25.540
Wow. Yeah. You can see those Ruby workers really struggling with the renaming, all those forks.

00:06:25.540 --> 00:06:30.100
I think we were the, I don't know, someone at GitHub may confirm this, but I think we were the first big

00:06:30.100 --> 00:06:36.020
project to do the renaming. Something went wrong. And it was very funny because I literally said,

00:06:36.020 --> 00:06:41.780
how funny will it be if now I get a 500? There you go. A 500 on the screen. Yeah. Yeah. It's recorded.

00:06:41.780 --> 00:06:46.340
There is someone actually recorded that clip. Yeah. Yeah. So I said, wow, man, this has been a

00:06:46.340 --> 00:06:51.380
such excitement thing that I can break such a big project. Let's do it more. So I decided also to

00:06:51.380 --> 00:06:57.540
stream the 310 release itself. And I said, well, technically the release, the final release is,

00:06:57.540 --> 00:07:03.140
is, is, is even more boring and longer. So that is actually probably not going to be even like,

00:07:03.140 --> 00:07:06.980
you know, something that someone went to see. So I said, okay, let's, let's not do it alone.

00:07:06.980 --> 00:07:12.020
So I invited a bunch of friends and core developers so they can actually talk about, you know, the things

00:07:12.020 --> 00:07:18.420
that they worked on the Python 3.10 release and a brand that needed were there so that they can,

00:07:18.420 --> 00:07:22.740
they can probably tell you how they found out. But like, apparently it was something that a lot of

00:07:22.740 --> 00:07:28.740
people enjoy because, you know, it's not only a opportunity to see how the sausage is made because,

00:07:28.740 --> 00:07:32.660
you know, I was just explaining all the commands and all the faces and whatnot, but like when something

00:07:32.660 --> 00:07:37.540
became very boring, then, you know, like brand and it were there to save the day and explain the cool

00:07:37.540 --> 00:07:42.500
things they, they work on. So, you know, which is a very good opportunity because, you know, when is

00:07:42.500 --> 00:07:47.060
the last time you could hear the author of the feature that you love, talk about the feature that

00:07:47.060 --> 00:07:48.900
you love. That is fantastic. And it happened.

00:07:48.900 --> 00:07:54.580
Right. And not only did it happen, but as they were explaining the feature that they built,

00:07:54.580 --> 00:08:00.180
the action of it being delivered to the entire world was right. It was like all coming together in a

00:08:00.180 --> 00:08:04.500
pretty awesome way. Exactly. And I could only do that just to be fair also, and, you know,

00:08:04.500 --> 00:08:10.100
create what credit is due. I could only do that because the first time I did the live thing,

00:08:10.100 --> 00:08:14.900
I was also doing all the, you know, pushing all the buttons and at the same time doing all the video

00:08:14.900 --> 00:08:20.020
stuff with, I don't know what is the software to the stream, but like whatever. And the second time we

00:08:20.020 --> 00:08:26.900
use the help of the Python discord team, which are fantastic. And they, they help us a lot. They,

00:08:26.900 --> 00:08:32.980
they, they have this fantastic UI where, you know, all the questions that were asked on the chat,

00:08:32.980 --> 00:08:38.420
there are some on the screen and we couldn't use it. Do you know why? Because Facebook or now Meta

00:08:38.420 --> 00:08:44.500
decided to break DNS globally. What an incredible fit, just in time. I think one.

00:08:44.500 --> 00:08:50.660
So what I'm learning is if we need some sort of like big cloud global outage, you all just need to live.

00:08:50.660 --> 00:08:58.260
Just call Pablo. Yes, exactly. Exactly. Just hire me today. So yes, that, that, that, now we were like

00:08:58.260 --> 00:09:02.500
two big outages on, on Python release. The, you know, there is only a line that passes through two points, but I, you know, it was a, it was a, it was a, it was a, it was a, it was a, it was a good, a good statistic already. So we said, what can, what else can we break? So there you go. We decided to do the three levels.

00:09:02.500 --> 00:09:31.500
release again. Then Mark was there as well, which increases the probability of things being broken by a lot. Sorry, Mark. I had to do the joke. He also fixes them. So, you know, it's fine and nothing broke. So, so kudos to Mark. Everything. Thanks to that. And we did the release. So, so we did the same thing.

00:09:31.500 --> 00:10:00.500
We explained the whole thing. So people could see from the authors themselves, like why all the switches are very cool. And I did the non boring parts of the release. And then we have a bit of some dramas in backstage because my Juviki that I used to sign release broke and I freak out quite a lot, but I thankfully have a backup Juviki. So nobody had, yeah, yeah. So crazy. Because if I didn't have that, then I will have to stop the whole thing, but we didn't have to do that.

00:10:00.500 --> 00:10:10.540
So yeah, it was just backstage. So yeah, quite, quite exciting. Nothing broke except my Juviki. I suppose that's the third thing that broke. It's not a global, you know, software, but I still mourn it. It's here.

00:10:10.540 --> 00:10:15.940
Yeah. It served you well, but now it's, it gave its life for Python 3.11.

00:10:15.940 --> 00:10:18.320
Too much power. Like 3.11 was too powerful.

00:10:18.320 --> 00:10:19.100
It just broke.

00:10:21.000 --> 00:10:22.920
This is a dangerous job that you got.

00:10:22.920 --> 00:10:23.800
Yeah, yeah, yeah.

00:10:24.500 --> 00:10:29.140
But you've handed it off, right? This is your last time, last main release.

00:10:29.140 --> 00:10:37.980
Yeah, yeah. I need to do the security and bug fix releases, but I don't need to do the ones that, you know, you need to chase people down and ask for like cherry picking.

00:10:37.980 --> 00:10:40.580
And there was a bunch of things of the release that were quite boring.

00:10:40.740 --> 00:10:51.420
Like normally we release the previous version, like before the final version, there is something called the release candidate, which is, you know, like the last version that people need to try out before we do the final release.

00:10:51.500 --> 00:10:59.140
And ideally that is the last version that we publish. Normally it means that you publish from that commit, but this is not the case.

00:10:59.140 --> 00:11:08.520
This is the first release that had 130 something commits on top of that, but I have to painstakingly cherry pick and it was not fun, but I did that before the release.

00:11:08.520 --> 00:11:13.460
It's like two hours because you need to fix conflicts and things like that. Yeah. Very, very boring.

00:11:13.460 --> 00:11:17.720
But yeah, I started the stream with that already done. So it was fine.

00:11:17.720 --> 00:11:18.580
Yeah. Fantastic.

00:11:18.880 --> 00:11:33.020
Now, before we get into all the features and I want to maybe just talk a little bit about some of the tools for actually doing the release and maybe start with you is what, what is 3.11 mean for you all getting this out?

00:11:33.020 --> 00:11:36.120
What does that mean for the Python community from your perspective?

00:11:36.120 --> 00:11:42.980
Well, 3.11 is, it is a huge release. There's a lot packed into it compared to the last few releases.

00:11:42.980 --> 00:11:48.520
There are no features. There's the performance work. It's, it's just massive changes internally.

00:11:48.520 --> 00:12:03.360
It's, it's just a huge release. And personally, I've started working on, you know, exception groups about two years ago. So for me, this is, it almost feels like finishing another PhD or something. It's, it's a massive kind of effort. And here it is. It's done.

00:12:03.360 --> 00:12:03.860
Yeah.

00:12:03.860 --> 00:12:08.920
It was a big day Monday. I had a bottle of champagne ready for the stream. It was a celebration.

00:12:08.920 --> 00:12:10.880
Yeah, it was. Brent, how about you?

00:12:11.120 --> 00:12:35.100
I'm really excited about 3.11 because I think there's something for everyone. And I think you'd be hard pressed to find someone who doesn't want their code to run faster and who doesn't want better error messages. And then you have all these other improvements on top of that. It's really nice to see both these like new features, which are something that we get in most Python releases, but also just the stuff that's there for everyone else who just wants to upgrade Python and just have a better experience all around.

00:12:35.100 --> 00:12:36.460
Yeah, I totally agree with that.

00:12:36.460 --> 00:12:58.660
It's cool to see people's responses to that too, because responses have been really, really positive, which is another thing that I liked about the live stream because we did, you know, live Q&A and we had the chat and everything going on. And when you're staring at the same code base for like a year, you're like, okay, I'm pretty sure that what we've done here is really, really cool. But, you know, like, is it actually as awesome as I think it is? You know, or have I just been staring at it for too long?

00:12:58.660 --> 00:12:59.060
Yeah.

00:12:59.060 --> 00:13:03.860
And then release it to the world and people are even more stoked about it than you are. And that's a really good feeling.

00:13:03.860 --> 00:13:05.880
Yeah, it is. Awesome. Mark?

00:13:06.020 --> 00:13:11.600
Yeah, well, I guess I started on trying to get Python faster 15 years ago, I guess, early PhD time.

00:13:11.600 --> 00:13:12.720
Yeah, with Hot Pie, right?

00:13:12.720 --> 00:13:24.020
Yeah, yeah. So that was a long, long. This has been a long time coming. So yeah, it's amazing to have it actually out and starting to see the speed ups. And obviously we're keeping working on it. So it's pretty good.

00:13:24.020 --> 00:13:37.460
Yeah, fantastic. You must be really proud because like you said, you have been proposing this for a really long time. You've had a lot of ideas. And finally, you've got a group of people working on it. And you're all on the same team with Mark and Guido.

00:13:37.800 --> 00:13:46.280
Yeah. And just making legitimate, serious progress here. So it's, you must be really proud to just sort of see this actually go out the door.

00:13:46.460 --> 00:13:47.160
Yes, definitely.

00:13:47.160 --> 00:13:53.160
Especially in main Python too. It's really nice that we're able to, you know, deliver this for everyone.

00:13:53.340 --> 00:14:03.220
Yeah. For me, I see basically three things like, kind of like you said, Brent, I see that obviously there's these new features like exception groups, which are lovely and make the language better.

00:14:03.220 --> 00:14:11.740
But it also gets friendlier for, especially for beginners, but for everyone, of course, with the better error messages and better reporting and tracebacks.

00:14:11.740 --> 00:14:17.640
And it gets faster. And so, I mean, it, and all the axes that seem to matter. It's, it's really fantastic.

00:14:17.720 --> 00:14:30.680
Okay. So let's dive in. I just, Pablo, let's go back just a little bit to the release process because people got to watch you do it, but they didn't actually, you know, see exactly what you're typing on your screen the whole time.

00:14:30.680 --> 00:14:39.540
It was more of about a, like an event of it. Sometimes your screen was up, sometimes it wasn't, but there's an official PEP that talks about like, here's the recipe for doing this, right?

00:14:39.540 --> 00:14:46.620
That is correct. It's PEP 101 doing Python releases. And that is a curious document. It's peculiar document.

00:14:46.860 --> 00:14:56.280
It talks about how it's done, but it's like, it's kind of weird. So the document is up to date. Like you can actually, you know, search PEP 101 and it will show you the thing.

00:14:56.280 --> 00:15:06.820
So what is there is the actual process. It's just, it also contains these weird sentences. Like if you search for it, there is a bunch of places that says stop, stop, stop, stop, stop, stop.

00:15:07.020 --> 00:15:16.440
And that was quite funny. And that was a, if I recall correctly, Larry Hastings, that he wrote those things. And the idea is that he could search for those places.

00:15:16.440 --> 00:15:25.860
And he knows that at that stage he needs to wait for something to happen or something. And we left it there. So there's a bunch of like weird artifacts.

00:15:25.860 --> 00:15:43.160
And, you know, it's full of bullet points because you, some stages you need to do some things and some others and things like that. And, you know, it says, okay, if you're running a beta release, then you need to do this bunch of things. And if you're running an alpha release, you need to do this bunch of things. And I have done the, I have done a state machine that goes through the whole thing.

00:15:43.160 --> 00:16:08.200
And I have done the whole thing because like, if you actually write this down is quiet, is it, you know, the, the, how is this called the maintainability index of this process is insane. It is just rejects your thing. Just don't, don't merge it. Right. And I said like, yeah, I'm not doing this reading. So one thing I did, which is the thing that I was using at the, at the stream, my first work as a release manager is say, I'm not going to do this by hand. And that is the vision.

00:16:08.200 --> 00:16:38.020
And then I did this script that is on a, github.com/Python slash release tools. And it's a, it's my attempt at automating this process as much as possible, which unfortunately, you know, it still requires a bunch of manual steps because like that's life and things happen, but, it's quite automatic. Like at least things that are not like final releases. So alpha and release candidates are now that we are in backfix releases, it mostly runs automatically, except that, you know, in the final release,

00:16:38.020 --> 00:16:47.440
everything fails because there's the final release for you. And then you need to fix things manually. So you, I think you saw me, you know, executing a bunch of those fixes at some point.

00:16:47.440 --> 00:16:58.720
And I added a division by zero just to know that something was hit. And that was seen on the screen because like, and people were like division by zero. Why do you need that to release Python? I don't know. That's very complicated.

00:16:58.720 --> 00:17:01.780
I could have asserted false. Come on. Anything wouldn't work.

00:17:01.780 --> 00:17:04.700
No, no. We divide by zero. I'm a physicist. So that's what I do.

00:17:04.700 --> 00:17:05.020
Okay.

00:17:06.020 --> 00:17:08.720
You studied black holes, right? Yeah.

00:17:08.720 --> 00:17:13.900
You were looking for some sort of like infinite sort of thing there divided by zero. Yeah.

00:17:13.900 --> 00:17:17.700
I'm too tired for today. Let's just collapse the universe divided by zero.

00:17:17.700 --> 00:17:22.940
Oh, but Python was too friendly. Instead of collapsing the universe, it sold me an exception, you know, quite nice.

00:17:22.940 --> 00:17:28.160
Only in 311. No, no, I'm joking. Anyway. So yes, yes. You can follow this PEP and, you know,

00:17:28.260 --> 00:17:38.440
just enjoy the whole process on its glory or you can see the script, but yeah, it's quite verbose. You can see that it's very, it's lots of places when everything can go wrong and you can panic.

00:17:38.820 --> 00:17:50.200
Now we know one more, apparently your Juviki can break. So that's something that can happen as well. But like, you know, it's quite annoying. And that's the main job of the release manager. Go through this annoying process. So yeah.

00:17:50.200 --> 00:17:59.160
Yeah. I see that there's some parts in here. You should have a few more stops. I should say, stop, stop, stop. Make sure GitHub still works. Stop, stop, stop. Make sure Azure still works. Stop, stop, stop.

00:17:59.160 --> 00:18:02.720
Yeah. Don't cry. Don't cry at this stage. Everyone is looking at you.

00:18:03.720 --> 00:18:14.700
But yeah, the one thing that is not in this PEP is that you also are in charge in theory of this extreme abstract mandate, which is that you're in charge of the stability of the release, whatever that means.

00:18:14.700 --> 00:18:27.040
That translates mostly on chasing people because they broke things. Another unfortunate event that we are trying to also fix a bit for the releases is that most people turn to the release manager to solve problems.

00:18:27.040 --> 00:18:36.800
So they say, Hey, this person says that we should do X while this other person says that we should do Y. We need someone to decide. Let's, let's, let's, let's reach the release manager.

00:18:36.800 --> 00:18:45.440
But the release manager is this guy on the corner. Like he doesn't know shit. So I like, you know, it's not the best, not the best person to fetch it. But everybody was like, what do you think, Pablo?

00:18:45.440 --> 00:18:51.500
So we merged this. I'm like, I don't know, man, this is some enum things. Like, I don't know about this. I have no context whatsoever.

00:18:51.500 --> 00:18:54.420
Your only concern is, will it still build and shift?

00:18:54.420 --> 00:19:09.740
Exactly. Like how, like, yeah, what about these 2000 lines of code that sold this tiny bag? It was like, well, maybe let's not merge that. But yeah, like we are trying to also like, you know, redirect all of this to the steering council, which also I am in the steering council. So apparently I'm not going to get rid of these questions.

00:19:09.740 --> 00:19:19.900
I'm joking. I enjoy all these questions, but as a release manager, I don't. So I like the key here is that the release manager should not take unilateral decisions on the evolution of these things because like it's just the release manager.

00:19:19.900 --> 00:19:22.040
So the reason the steering council is five people.

00:19:22.040 --> 00:19:26.200
But you are the one who delivers the code. You could kind of, you could sneak a feature in there.

00:19:26.200 --> 00:19:32.320
No, no, no. I don't decide important things. I just execute and chase people. And I'm this annoying guy that says, you broke this, fix it.

00:19:32.320 --> 00:19:38.720
But like then if there is some important decisions to be taken, you know, that's the steering council job, which is five people.

00:19:38.960 --> 00:19:47.020
Because, you know, one person shouldn't decide these things. It's like, and this happens. Like sometimes I say, hey, there is this PR when people are asking, what should we do?

00:19:47.020 --> 00:19:53.860
And then this is my opinion as the member of the steering council and the other four members, maybe they say, well, actually, that's not a good opinion.

00:19:54.100 --> 00:20:00.240
So what about this? You know, we ended in a much better place because it was five people, five persons doing a decision instead of one.

00:20:00.240 --> 00:20:07.400
This portion of Talk Python To Me is brought to you by Microsoft for Startups Founders Hub.

00:20:07.400 --> 00:20:14.420
Starting a business is hard. By some estimates, over 90% of startups will go out of business in just their first year.

00:20:14.420 --> 00:20:23.880
With that in mind, Microsoft for Startups set out to understand what startups need to be successful and to create a digital platform to help them overcome those challenges.

00:20:24.320 --> 00:20:33.220
Microsoft for Startups Founders Hub was born. Founders Hub provides all founders at any stage with free resources to solve their startup challenges.

00:20:33.220 --> 00:20:41.840
The platform provides technology benefits, access to expert guidance and skilled resources, mentorship and networking connections, and much more.

00:20:41.840 --> 00:20:51.400
Unlike others in the industry, Microsoft for Startups Founders Hub doesn't require startups to be investor backed or third party validated to participate.

00:20:51.400 --> 00:20:54.120
Founders Hub is truly open to all.

00:20:54.120 --> 00:20:55.620
So what do you get if you join them?

00:20:55.620 --> 00:21:03.880
You speed up your development with free access to GitHub and Microsoft Cloud computing resources and the ability to unlock more credits over time.

00:21:03.880 --> 00:21:13.600
To help your startup innovate, Founders Hub is partnering with innovative companies like OpenAI, a global leader in AI research and development, to provide exclusive benefits and discounts.

00:21:13.600 --> 00:21:19.040
Through Microsoft for Startups Founders Hub, becoming a founder is no longer about who you know.

00:21:19.360 --> 00:21:32.580
You'll have access to their mentorship network, giving you a pool of hundreds of mentors across a range of disciplines and areas like idea validation, fundraising, management and coaching, sales and marketing, as well as specific technical stress points.

00:21:32.580 --> 00:21:37.800
You'll be able to book a one-on-one meeting with the mentors, many of whom are former founders themselves.

00:21:37.800 --> 00:21:42.940
Make your idea a reality today with the critical support you'll get from Founders Hub.

00:21:43.120 --> 00:21:48.900
To join the program, just visit talkpython.fm/founders hub, all one word, no links in your show notes.

00:21:48.900 --> 00:21:51.200
Thank you to Microsoft for supporting the show.

00:21:52.980 --> 00:21:53.340
Amazing.

00:21:53.340 --> 00:21:56.840
Okay, so if people want to follow along with the process, they can check out PEP 101.

00:21:56.840 --> 00:21:58.160
Let's keep over here.

00:21:58.160 --> 00:22:04.080
You also talked about the Python build bot that people can check out, but I think maybe we want to jump into our first feature.

00:22:04.080 --> 00:22:12.920
There's, as Arit said, there's a ton of features and things in here, but there's also maybe some top-level ones that'll be really important for a lot of folks.

00:22:12.920 --> 00:22:15.560
And Arit, you want to tell us about your work?

00:22:15.560 --> 00:22:18.200
You mentioned before the exception groups and exception star.

00:22:18.360 --> 00:22:29.780
This is kind of a major new feature that we added, and the idea is that sometimes you'll have a situation where you did several things and maybe more than one of them raised an exception.

00:22:29.780 --> 00:22:33.760
And now you need to report that there was more than one error in whatever you did.

00:22:33.760 --> 00:22:40.380
And what you did could have been a bunch of asynchronous tasks, which is, that was the use case that motivated this whole thing.

00:22:40.660 --> 00:22:50.080
But there are also situations where you just iterate over a few things and repeat them and accumulate exceptions, and you want to kind of report all of them.

00:22:50.080 --> 00:22:55.300
And the PEP lists a bunch of examples of where this can happen.

00:22:55.300 --> 00:23:05.300
So people, typically what they do is they'll take a list of exceptions, wrap it in another exception, multi-error, some other kind of wrapper, and throw that.

00:23:05.300 --> 00:23:06.260
And then you have to catch it.

00:23:06.260 --> 00:23:09.120
And then you have to iterate over the list and look at the exceptions.

00:23:09.120 --> 00:23:12.200
But you don't have a method to handle the exceptions.

00:23:12.200 --> 00:23:16.120
Like you have try accept, like catch these, but not catch exceptions.

00:23:16.120 --> 00:23:16.740
Right, right.

00:23:16.740 --> 00:23:23.260
Because in accept, you might have like accept socket error, or you might have accept like file not found type of thing.

00:23:23.260 --> 00:23:28.700
But if those both happen, neither of those would run in Python 3.10, right?

00:23:28.700 --> 00:23:31.700
Because it's some kind of weird wrapper, and it's not a socket exception.

00:23:31.700 --> 00:23:34.040
It's not a file exception, but it kind of contains both.

00:23:34.040 --> 00:23:36.200
And so in a sense, you can both run?

00:23:36.200 --> 00:23:36.660
I don't know.

00:23:36.660 --> 00:23:43.800
And then if you catch the wrapper, and you do something with some of the exceptions, you better not forget to erase the rest because you're not handling them.

00:23:44.220 --> 00:23:47.400
So yeah, there are a lot of problems when you try to work around this.

00:23:47.400 --> 00:23:49.640
And like what happened with Trio.

00:23:49.640 --> 00:23:58.500
So Trio had multi-error, would raise this wrapper, and it had to do a lot of complicated acrobatics just to have some error handling.

00:23:58.500 --> 00:24:05.220
So the motivation was, yeah, we have task groups in Python 3.11, which are kind of like Trio nurseries.

00:24:05.220 --> 00:24:09.640
Kind of a structured collection of asynchronous tasks.

00:24:09.640 --> 00:24:12.000
And task groups were on the cards.

00:24:12.360 --> 00:24:17.040
He started, like Yuri Selibanov, who was kind of maintaining asyncio in the beginning.

00:24:17.040 --> 00:24:18.360
He wrote a lot of asyncio.

00:24:18.360 --> 00:24:23.860
He wanted to add task groups since 2017, 2018, something like that.

00:24:23.860 --> 00:24:26.720
And what was holding it up was error handling.

00:24:26.720 --> 00:24:29.020
There was no good way to handle errors.

00:24:29.300 --> 00:24:34.340
So now we have accept star, which generalizes accept and works with groups.

00:24:34.340 --> 00:24:44.140
So you can say accept star socket error, and then it will just extract all the socket errors from the group and give you those and automatically re-erase everything else.

00:24:44.140 --> 00:24:45.740
That's basically the idea.

00:24:45.980 --> 00:24:46.700
This is pretty interesting.

00:24:46.700 --> 00:24:51.420
We have try, do your thing, and then accept star, you know, one error type.

00:24:51.420 --> 00:24:53.300
Accept star, another error type.

00:24:53.300 --> 00:24:55.500
Accept star, a set of errors, potentially.

00:24:55.500 --> 00:25:08.680
So what happens if I'm in this situation and, say, the first error type and maybe something from the third error catch clause is thrown in one of these task groups, exception groups?

00:25:08.780 --> 00:25:12.740
Each exception in the group will be handled by at most one of the clauses.

00:25:12.740 --> 00:25:18.240
So the first clause that matches its type will consume it, and each clause executes once.

00:25:18.240 --> 00:25:28.620
So if there are more than one errors of that type, then what gets kind of bound in the accept star full error as e, what gets bound to e is a group of full errors.

00:25:28.620 --> 00:25:35.840
So you get all the full errors in a group, execute that clause, and then move on to the next clause with whatever is not handled yet.

00:25:35.840 --> 00:25:36.580
Interesting.

00:25:36.880 --> 00:25:39.280
So it might run two of the clauses.

00:25:39.280 --> 00:25:40.300
Exactly.

00:25:40.300 --> 00:25:45.980
Whereas in traditional exception handling, it goes from top to bottom, and it looks for an inheritance type of match.

00:25:45.980 --> 00:25:47.780
And the first one that matches, that's it.

00:25:47.780 --> 00:25:51.000
But in this case, with the star, you could get multiple ones.

00:25:51.000 --> 00:25:58.160
I guess the star, to me, when I look at this, the star is reminiscent of Argg's star, where you have...

00:25:58.160 --> 00:25:59.140
Unpacking, yeah.

00:25:59.140 --> 00:26:00.380
Yeah, yeah, exactly.

00:26:00.380 --> 00:26:06.020
It's not exactly unpacking, but it was kind of the intention to make it look a bit like unpacking.

00:26:06.020 --> 00:26:06.320
Nice.

00:26:06.320 --> 00:26:08.080
Yeah, this looks like a really cool feature.

00:26:08.080 --> 00:26:12.140
You talked about the task groups and trio and those things.

00:26:12.140 --> 00:26:15.320
So when I saw this, concurrent errors obviously come to mind.

00:26:15.320 --> 00:26:25.140
Because if I try to both write something to a database and call a web service asynchronously, and I start both of those, and they both crash, or multiple ones crash, which error do you want?

00:26:25.140 --> 00:26:25.840
The database error?

00:26:25.840 --> 00:26:26.900
Or do you want the API error?

00:26:26.900 --> 00:26:28.560
You probably want to know about both of them, right?

00:26:28.600 --> 00:26:31.420
So that's a real natural reason to bring these together.

00:26:31.420 --> 00:26:36.180
But maybe you'll also list out some of the other reasons that you might run into this.

00:26:36.180 --> 00:26:37.780
Maybe give people some other ideas.

00:26:37.780 --> 00:26:41.660
So the example of the socket module, we have the create connection function.

00:26:41.660 --> 00:26:44.400
And that function, I was showing it in the stream.

00:26:44.400 --> 00:26:49.320
It iterates over all the configurations that you could try to connect with.

00:26:49.320 --> 00:26:52.960
And then depending on what's going on the other side, hopefully one of them works.

00:26:52.960 --> 00:26:55.460
But if none of them work, you have to report errors.

00:26:55.460 --> 00:26:59.160
And what we do in Python 3.10 is we just raise the last exception.

00:26:59.160 --> 00:27:01.380
So you don't know what happened, really.

00:27:01.380 --> 00:27:04.000
You only know why the last attempt failed.

00:27:04.000 --> 00:27:06.440
You don't even know how many attempts were made to connect to.

00:27:06.440 --> 00:27:08.560
How many configurations did we try?

00:27:08.560 --> 00:27:14.140
So that was a long-standing open problem, kind of, can we do better than just for the last error?

00:27:14.140 --> 00:27:15.540
And we closed it.

00:27:15.540 --> 00:27:17.220
We just added it for us to that.

00:27:17.220 --> 00:27:18.680
Give me a demo for the group.

00:27:18.680 --> 00:27:23.260
Another place that comes to mind is, maybe you'll be familiar with some of these retry libraries.

00:27:23.260 --> 00:27:23.700
Yeah.

00:27:23.700 --> 00:27:28.980
Like, retry, but I think there's others as well, where you put a decorator onto some function.

00:27:28.980 --> 00:27:31.360
You say, try this multiple times.

00:27:31.360 --> 00:27:36.140
And if it fails, do, like, some sort of exponential backoff because maybe the server's overloaded.

00:27:36.140 --> 00:27:36.520
Right?

00:27:36.520 --> 00:27:38.560
Those types of things would be really great.

00:27:38.560 --> 00:27:43.540
Like, if it retries all the times it's supposed to and it fails, it'd be good to get all the errors,

00:27:43.540 --> 00:27:47.200
not just the last one or the first one or whatever it decided it was going to give you.

00:27:47.200 --> 00:27:47.620
Yeah.

00:27:47.620 --> 00:27:47.860
Yeah.

00:27:47.860 --> 00:27:48.720
It's the kind of thing.

00:27:48.720 --> 00:27:49.180
Exactly.

00:27:49.180 --> 00:27:49.540
Yeah.

00:27:49.540 --> 00:27:50.020
Nice.

00:27:50.020 --> 00:27:50.560
Okay.

00:27:50.560 --> 00:27:52.500
Well, congratulations on getting that feature out.

00:27:52.500 --> 00:27:53.180
That's great.

00:27:53.640 --> 00:27:53.840
All right.

00:27:53.840 --> 00:27:54.920
What do we got next here?

00:27:54.920 --> 00:28:00.880
I think also related to this, I wanted to talk about this PEP678.

00:28:01.000 --> 00:28:07.420
That's a very small and simple feature that Zach had for Dodds wrote this PEP.

00:28:07.420 --> 00:28:09.200
He was trying out exception groups.

00:28:09.200 --> 00:28:11.120
He was the first kind of user.

00:28:11.120 --> 00:28:13.700
Even before the PR was merged, he was trying it out.

00:28:13.700 --> 00:28:16.860
He was trying to integrate it with the hypothesis library.

00:28:17.000 --> 00:28:25.120
So there you write a test and the library executes it many times with different inputs and you get failures in some of the inputs and you want to report all of them.

00:28:25.120 --> 00:28:26.360
So Zach had an exception group.

00:28:26.360 --> 00:28:30.240
So Zach had an exception group, kind of an exception wrapper, kind of like Trio multi-error.

00:28:30.240 --> 00:28:41.620
He had his own version that he built in his library and he could associate each exception he attached to it, which inputs generated this error, which is very important.

00:28:41.620 --> 00:28:45.180
You need to tell people what the input was and what happened with it.

00:28:45.180 --> 00:28:49.940
And he couldn't do that in a convenient way with exception groups.

00:28:49.940 --> 00:28:53.320
So we added this to base exception.

00:28:53.320 --> 00:28:54.920
This is not a group feature.

00:28:54.920 --> 00:28:55.800
It's any exception.

00:28:55.800 --> 00:28:57.360
You can add strings.

00:28:57.360 --> 00:29:08.560
You call add note, give it a string and you can call it as many times as you want and add notes to the exceptions and they will appear in the default trace pack that the interpreter prints.

00:29:08.560 --> 00:29:09.620
So that's all it is.

00:29:09.620 --> 00:29:13.520
It's a very simple feature, but it was received surprisingly well.

00:29:13.520 --> 00:29:18.060
People kind of like it that you can enrich an exception after you catch it.

00:29:18.060 --> 00:29:23.700
So you have the information that, you know, the error message and the type, you decide that when you raise the exception.

00:29:23.700 --> 00:29:30.080
But then sometimes when you're catching, there's some more information, some context, like what was I trying to do when this error happened?

00:29:30.080 --> 00:29:30.520
Sure.

00:29:30.520 --> 00:29:31.060
Yeah.

00:29:31.060 --> 00:29:37.760
Because often you'll see, except some type, some exception type, you'll deal with what you can, but you can't really handle it there.

00:29:37.760 --> 00:29:38.740
So you got to raise it again.

00:29:38.740 --> 00:29:43.020
And this is a place to add more information without completely wrapping it.

00:29:43.020 --> 00:29:43.280
Right.

00:29:43.280 --> 00:29:43.640
Right.

00:29:43.640 --> 00:29:44.120
Exactly.

00:29:44.120 --> 00:29:48.280
A lot of people have to chain it, say this raised from that.

00:29:48.280 --> 00:29:52.040
So there will be situations where maybe you won't need to do that.

00:29:52.040 --> 00:29:52.380
Yeah.

00:29:52.380 --> 00:29:53.960
I'd love to see that go away.

00:29:53.960 --> 00:29:57.360
I don't sort of template libraries and stuff in the web all the time.

00:29:57.360 --> 00:30:02.320
I see like there's all these different errors and you got to hunt through a bunch of stuff to figure out what happened.

00:30:02.420 --> 00:30:02.620
Yeah.

00:30:02.620 --> 00:30:02.660
Yeah.

00:30:02.660 --> 00:30:11.060
But also think about, for instance, like I think this is super useful actually for end users even like you think about that you're doing some query to the database.

00:30:11.060 --> 00:30:11.320
Right.

00:30:11.320 --> 00:30:14.100
And then I don't know, it may fail for six million reasons.

00:30:14.100 --> 00:30:16.980
And then you want to add what you're asking for.

00:30:16.980 --> 00:30:17.320
Right.

00:30:17.320 --> 00:30:27.400
So you add your query or your user or whatever, because probably the exception that the Postgres thingy that is underneath is not going to contain your actual thing.

00:30:27.400 --> 00:30:30.540
So this actually may save you hours, right?

00:30:30.540 --> 00:30:35.840
Because in many enterprise environments, you don't even have easy access to that.

00:30:35.840 --> 00:30:36.560
Sorry, to prod.

00:30:36.560 --> 00:30:39.720
So you cannot just go there and see what's going on.

00:30:39.720 --> 00:30:47.140
So it would be super cool that you say, if something fails, you know, I was trying to do this with this data and like with these things.

00:30:47.140 --> 00:30:51.860
And like if it fails now, you can know what's going on and you don't even need to log in, which is I think it's a.

00:30:51.860 --> 00:30:52.960
Yeah.

00:30:52.960 --> 00:30:53.280
Yeah.

00:30:53.280 --> 00:30:54.240
It's a great idea.

00:30:54.240 --> 00:30:59.340
Or if you know, look, here's probably why this happened as a library developer.

00:30:59.340 --> 00:31:00.840
You're like, look, this is the error.

00:31:00.840 --> 00:31:01.900
But here's a note.

00:31:01.900 --> 00:31:05.660
This is probably because you didn't initialize the connection before you called this.

00:31:05.660 --> 00:31:15.000
So make sure, you know, like another area where I see this could be useful is I want to raise like the example you have in the docs is type error.

00:31:15.000 --> 00:31:19.480
But it could also, you know, it could be value error or some other built in low level type.

00:31:19.480 --> 00:31:25.120
You're like, really, this is just I want to raise that error, but it doesn't have a place for me to put additional information.

00:31:25.120 --> 00:31:27.860
And so I want to kind of enrich that with more.

00:31:27.860 --> 00:31:30.820
And so not just catch, add the data and then raise it again.

00:31:30.820 --> 00:31:35.600
But actually, I want to use a base error type that doesn't let me put more details in it and then just raise that.

00:31:35.600 --> 00:31:35.840
Right.

00:31:35.840 --> 00:31:36.640
That would also work.

00:31:36.720 --> 00:31:37.200
I think so.

00:31:37.200 --> 00:31:45.480
I mean, I think the intention was there was some discussions about using notes in the interpreter and I pushed back on it because I said this is owned by the application.

00:31:45.480 --> 00:31:49.780
The interpreter shouldn't touch the notes, you know, because people can wipe out the notes.

00:31:49.780 --> 00:31:50.720
They can change the order.

00:31:50.720 --> 00:31:51.600
They can do what they want.

00:31:51.600 --> 00:31:54.740
It's the applications, at least the way I see it.

00:31:54.740 --> 00:31:55.720
The application owns it.

00:31:55.720 --> 00:31:57.800
You put whatever context you want to put.

00:31:57.800 --> 00:31:59.260
Is there only one note?

00:31:59.260 --> 00:32:03.140
When I say add note, does that set the note or can I have a list of notes?

00:32:03.140 --> 00:32:04.380
It's a list of notes.

00:32:04.380 --> 00:32:04.900
Okay, got it.

00:32:04.940 --> 00:32:06.400
Yeah, and you can wipe it out if you want.

00:32:06.400 --> 00:32:08.700
You can, it's just a list.

00:32:08.700 --> 00:32:10.020
It's attached to the exception.

00:32:10.020 --> 00:32:11.460
You can do what you want with it, really.

00:32:11.460 --> 00:32:11.720
Yeah.

00:32:11.720 --> 00:32:12.000
Cool.

00:32:12.000 --> 00:32:12.520
Okay.

00:32:12.520 --> 00:32:14.400
Yeah, it's a great, it's a really great feature.

00:32:14.400 --> 00:32:20.500
I mean, it's, I'm sure it was way less work than accept star, but it's also going to be really valuable, I think.

00:32:20.500 --> 00:32:22.140
It's very simple, but it's, yeah.

00:32:22.140 --> 00:32:22.440
Yeah.

00:32:22.440 --> 00:32:25.840
Brent or Mark, you guys got any thought about this before we move on to the next?

00:32:25.840 --> 00:32:26.760
I think it's really cool.

00:32:26.760 --> 00:32:27.640
I like it.

00:32:27.640 --> 00:32:28.360
Great work here.

00:32:28.360 --> 00:32:28.760
Indeed.

00:32:28.760 --> 00:32:30.080
I think it is as well.

00:32:30.080 --> 00:32:31.400
Actually, I'm really excited about it.

00:32:31.400 --> 00:32:34.920
I want to talk about, let's talk about faster Python.

00:32:34.920 --> 00:32:35.760
for a little bit.

00:32:35.760 --> 00:32:41.440
So, Mark, I had you and Guido on back on, wow, almost to the day a year ago.

00:32:41.440 --> 00:32:44.420
We're off by November 1st, 2021.

00:32:44.420 --> 00:32:47.780
So, not that long ago.

00:32:47.780 --> 00:32:50.800
Let's talk a little bit about the work that you're doing there.

00:32:50.800 --> 00:33:01.420
I guess the headline is that Python 3.11 is 10 to 60, 10 to 50% faster than previous, sort of on a reasonable range of applications.

00:33:01.420 --> 00:33:02.280
Is that the story?

00:33:02.280 --> 00:33:02.740
Yeah.

00:33:02.740 --> 00:33:08.440
It's somewhere between minus a few percent and plus 100, but it varies a huge amount.

00:33:08.640 --> 00:33:16.100
I mean, if you've got some application that basically spends all its time in NumPy or something like that, you're not really going to speed up at all.

00:33:16.100 --> 00:33:21.060
But if it's pure Python, you'd expect it to be a good 40, 50% faster.

00:33:21.060 --> 00:33:22.740
But it depends.

00:33:22.740 --> 00:33:23.020
Right.

00:33:23.080 --> 00:33:29.560
That's a good point because a lot of people do make Python faster by writing C or Rust or other languages.

00:33:29.560 --> 00:33:31.820
And at that point, like, it's out of your hands, right?

00:33:31.820 --> 00:33:32.140
Yeah.

00:33:32.140 --> 00:33:38.780
So, I mean, we're looking, hopefully, for 3.12 to start looking at the sort of interface between Python and C code.

00:33:38.920 --> 00:33:41.800
So, we should speed up code even though there's quite a lot of C code.

00:33:41.800 --> 00:33:49.000
We won't spend up the time spent in the C code in doing the actual work in the C code, but there's still quite a lot of sort of marshalling of data that happens.

00:33:49.000 --> 00:33:50.380
And hopefully, we'll streamline that.

00:33:50.380 --> 00:33:56.200
But the existence of C extensions is sort of, in some ways, limits our opportunity to speed things up.

00:33:56.200 --> 00:34:00.460
But it's also, you know, why Python is so proper in the first place are one of the main reasons.

00:34:00.460 --> 00:34:02.180
So, definitely need to acknowledge it.

00:34:02.180 --> 00:34:03.100
Yeah, absolutely.

00:34:03.100 --> 00:34:06.100
So, Brent, I'll definitely have you talk about the specializing interpreters.

00:34:06.800 --> 00:34:11.700
Mark, maybe give us a rundown of some of the things from your plan that made it in here.

00:34:11.700 --> 00:34:15.100
I know some were aimed for 3.10, but they didn't make it until here, right?

00:34:15.100 --> 00:34:15.500
Yeah.

00:34:15.500 --> 00:34:21.880
So, the whole thing, oh, that original plan I put up, that was more of a just to get the discussion going sort of thing.

00:34:21.880 --> 00:34:23.940
And it's basically, it's more or less a year off.

00:34:23.940 --> 00:34:26.120
So, if you just shift everything one forward.

00:34:26.120 --> 00:34:34.140
I mean, there was a lot of discussion on speeding up the interpreter in the first iteration and then looking more to the data structures in the second thing.

00:34:34.140 --> 00:34:35.740
It's much more jumbled than that.

00:34:35.740 --> 00:34:37.040
We're doing sort of a bit of everything.

00:34:37.040 --> 00:34:40.600
So, obviously, I was planning on, you know, expecting a smaller team.

00:34:40.600 --> 00:34:42.440
So, things are being a bit shuffled.

00:34:42.440 --> 00:34:44.900
So, yeah, there's a specializing interpreter.

00:34:44.900 --> 00:34:46.080
Obviously, that's kind of key.

00:34:46.080 --> 00:34:48.700
There's also quite a lot of stuff we've done with data structures.

00:34:48.700 --> 00:34:51.220
I mean, we shrunk the Python object.

00:34:51.220 --> 00:34:54.640
So, I mean, the Python object, you know, has been shrinking for years.

00:34:54.740 --> 00:34:56.860
I mean, I've got some numbers here.

00:34:56.860 --> 00:35:05.020
So, like in 2.7 and 3.2, like an object with just four attributes would take 352 bytes on a 64-bit machine.

00:35:05.020 --> 00:35:07.020
And for 3.11, we've got it down to 112.

00:35:07.020 --> 00:35:09.160
And for 3.12, it would be 96.

00:35:09.160 --> 00:35:12.640
Well, before you get too excited, there's only 32 in C++.

00:35:12.640 --> 00:35:14.780
So, you know, we've got a bit of a way to go.

00:35:14.900 --> 00:35:18.340
Yeah, but, you know, it's going in the right direction for sure.

00:35:18.340 --> 00:35:21.240
And, you know, I'm sure some people out there listening just say like,

00:35:21.240 --> 00:35:24.500
okay, well, it's half the size roughly and it's going to be less than that.

00:35:24.500 --> 00:35:26.600
So, yay, we can use less memory.

00:35:26.600 --> 00:35:34.160
But maybe you could talk a little bit about how that affects things like L1, L2, L3 cache hits and other sort of,

00:35:34.160 --> 00:35:37.400
like it's more important than just I need less RAM, right?

00:35:37.400 --> 00:35:37.840
Yeah, yeah.

00:35:37.840 --> 00:35:39.920
So, there's two things that happen.

00:35:39.920 --> 00:35:43.380
Yeah, things are faster because the hardware is just happier.

00:35:43.440 --> 00:35:46.220
If you pack everything together, it's in a high-level cache.

00:35:46.220 --> 00:35:50.100
So, you're not getting these sort of long pauses as you hit main memory.

00:35:50.100 --> 00:35:54.760
And the other thing is just the data structures are, because there's less of them, there's less indirection.

00:35:54.760 --> 00:36:00.620
So, for example, to load an attribute, we've got it down for basically an old, you know, older versions of Python.

00:36:00.620 --> 00:36:04.200
It was sort of effectively five memory reads and they were dependent memory.

00:36:04.200 --> 00:36:06.440
You have to read one before the next one and so on.

00:36:06.440 --> 00:36:06.780
Right, right.

00:36:06.780 --> 00:36:10.160
Go to the class, find its, go to the object, find its dictionary.

00:36:10.160 --> 00:36:10.920
Yeah.

00:36:10.920 --> 00:36:13.080
Then find the pointer that's in the dictionary and then go to that, right?

00:36:13.080 --> 00:36:13.700
Like it's...

00:36:13.700 --> 00:36:14.020
Yeah, yeah.

00:36:14.020 --> 00:36:15.280
Very much that.

00:36:15.280 --> 00:36:17.280
And it's down to more or less two now.

00:36:17.280 --> 00:36:18.060
Okay.

00:36:18.060 --> 00:36:18.800
That's pretty awesome.

00:36:18.800 --> 00:36:21.020
I mean, obviously, there's still interpretive overhead on that.

00:36:21.020 --> 00:36:26.000
So, it's not quite that much faster, but it's getting there.

00:36:26.000 --> 00:36:27.760
So, yeah, there's a data structure.

00:36:27.760 --> 00:36:36.320
And then the frames, the Python frames, every time you call a Python function, we used to just allocate a heap object for the frame and all this stuff would go in there.

00:36:36.320 --> 00:36:40.300
And now they're all basically in a big contiguous sort of block of memory.

00:36:40.300 --> 00:36:44.760
So, it's just bumping a pointer rather than allocating, which is also faster.

00:36:44.760 --> 00:36:52.720
And frames are just smaller anyway because of the zero cost exceptions, which I think we mentioned on the release thing.

00:36:52.720 --> 00:36:53.760
But, yeah, this is...

00:36:53.760 --> 00:36:55.900
Well, let's tell people about zero cost exceptions.

00:36:55.900 --> 00:36:56.500
Okay.

00:36:56.500 --> 00:36:57.380
Well, zero cost...

00:36:57.380 --> 00:37:00.020
You shouldn't have to pay for errors if you're not raising errors, right?

00:37:00.020 --> 00:37:00.320
Yeah.

00:37:00.320 --> 00:37:01.200
That's the idea.

00:37:01.200 --> 00:37:02.440
And that's why they're called zero cost.

00:37:02.440 --> 00:37:04.260
But zero cost is in quotes in this.

00:37:04.260 --> 00:37:07.640
And the reason for that is that's the name it has got.

00:37:07.640 --> 00:37:09.400
They're definitely not zero cost.

00:37:09.400 --> 00:37:13.220
The idea is that they're pretty low cost if you don't have an exception.

00:37:13.220 --> 00:37:17.580
But they tend to be even more expensive if you do get an exception because you have to do more lookup.

00:37:17.580 --> 00:37:23.160
The important thing here is that just there was lots of runtime information we need to maintain and we don't now.

00:37:23.160 --> 00:37:28.820
So, that, again, shrinks the frames and just makes calls faster because calls in Python were notoriously slow.

00:37:28.820 --> 00:37:31.380
So, that's one thing we've sped up significantly.

00:37:31.380 --> 00:37:31.760
Yeah.

00:37:31.760 --> 00:37:39.080
So, the idea was in previous releases of Python, if you just enter a try block, even if it was successful,

00:37:39.080 --> 00:37:44.880
there was a little bit of overhead to set up the mechanisms of potentially handling the errors and the information you needed, right?

00:37:44.880 --> 00:37:45.300
Yeah.

00:37:45.300 --> 00:37:47.060
And this wasn't just the overhead.

00:37:47.060 --> 00:37:48.140
You defer more of that, right?

00:37:48.140 --> 00:37:48.540
Yeah.

00:37:48.540 --> 00:37:58.240
I mean, it's actually not so much that overhead as just the space you had to put that data in had to be allocated every time you made a call in case there was an exception.

00:37:58.240 --> 00:38:02.640
And then we had to, it was massively over allocated to the amount of space anyone ever needed.

00:38:02.640 --> 00:38:04.760
So, just that was the big sort of advantage.

00:38:04.760 --> 00:38:05.320
Nice.

00:38:05.320 --> 00:38:05.640
Yeah.

00:38:05.640 --> 00:38:06.620
This is fantastic.

00:38:06.620 --> 00:38:11.320
You don't want to discourage people from putting proper error handling in their code.

00:38:11.320 --> 00:38:12.560
Yeah.

00:38:12.560 --> 00:38:13.200
What do you think?

00:38:13.200 --> 00:38:15.920
I see your name on this feature here in GitHub.

00:38:16.380 --> 00:38:17.060
What are your thoughts on it?

00:38:17.060 --> 00:38:17.400
Yeah.

00:38:17.400 --> 00:38:18.900
I think, I think it's cool.

00:38:18.900 --> 00:38:29.100
And I was kind of, you know, it was a nice touch that Mark implemented it between when I wrote the prototype for exception groups and when the PEP was approved.

00:38:29.100 --> 00:38:33.500
So, that got in the way a little bit.

00:38:33.500 --> 00:38:34.320
But it was good.

00:38:34.320 --> 00:38:39.320
I got intimately acquainted with zero-cost exceptions through that exercise.

00:38:39.320 --> 00:38:43.080
Well, it's zero-cost for some people.

00:38:43.520 --> 00:38:43.920
Yeah.

00:38:43.920 --> 00:38:43.960
Yeah.

00:38:43.960 --> 00:38:46.600
I tease Mark a lot about that.

00:38:46.600 --> 00:38:48.820
But no, I think it's a cool feature.

00:38:48.820 --> 00:38:51.820
And I mean, I followed up on that.

00:38:51.820 --> 00:38:59.080
We now have, after we removed that, we still had a, I was talking about this on Monday, we had a jump over the exception handler.

00:38:59.480 --> 00:39:01.980
And then I told Mark, wait a minute, there's a jump.

00:39:01.980 --> 00:39:02.640
It's not zero.

00:39:02.640 --> 00:39:05.800
You have to jump over the exception handler if there's no exception.

00:39:05.800 --> 00:39:11.400
So now we have, we did, we identify exception handlers as cold blocks.

00:39:11.660 --> 00:39:15.480
And before we lay out the code of the function, we put all the code blocks in the end.

00:39:15.480 --> 00:39:20.300
So now if there's no exception, there isn't even an exception handler to jump over.

00:39:20.300 --> 00:39:21.660
That would be in 3.12.

00:39:21.660 --> 00:39:22.260
Yeah.

00:39:22.260 --> 00:39:23.080
Excellent.

00:39:23.080 --> 00:39:25.160
You made zero-cost even faster.

00:39:25.160 --> 00:39:26.600
So now it's like, yeah.

00:39:26.600 --> 00:39:27.700
Zero even smaller.

00:39:27.700 --> 00:39:28.040
Yeah.

00:39:28.040 --> 00:39:31.180
It's asymptotically approaching zero.

00:39:31.180 --> 00:39:31.900
Yeah.

00:39:31.900 --> 00:39:38.400
So, but it's kind of nice that we have this notion of cold blocks and hot blocks and we can maybe do other things with it.

00:39:38.500 --> 00:39:46.060
Kind of nice that all the, all the happy, but the fast code is kind of in the beginning of the functions bytecode block.

00:39:46.060 --> 00:39:53.400
And, you know, in terms of caches and all that, you don't have to, I think it would, we bring a few benefits beyond just not having to jump.

00:39:53.400 --> 00:39:53.640
Yeah.

00:39:53.640 --> 00:39:54.120
Yeah.

00:39:54.120 --> 00:39:54.740
This is excellent.

00:39:54.740 --> 00:39:56.780
It's a really great feature and pretty straightforward.

00:39:56.780 --> 00:39:57.160
All right.

00:39:57.160 --> 00:40:00.320
Brent, tell us about the specializing adaptive interpreter.

00:40:00.320 --> 00:40:01.360
That's a big deal.

00:40:01.360 --> 00:40:04.220
You and I spoke about that about six weeks ago, I think.

00:40:04.220 --> 00:40:04.740
Yeah.

00:40:04.740 --> 00:40:04.980
Yeah.

00:40:05.400 --> 00:40:10.660
Basically, the headline is the bytecode changes while it's running to adapt to your code, which is really neat.

00:40:10.660 --> 00:40:18.080
So it's kind of finding places where we can do the same thing, but using less work by like cheating a little bit.

00:40:18.080 --> 00:40:21.380
But cheating in a way that is not visible at all.

00:40:21.380 --> 00:40:27.520
A good example is something like a global load or a load from the built-in.

00:40:27.520 --> 00:40:31.900
So if I'm looking at like the len function, that requires two dictionary lookups.

00:40:31.900 --> 00:40:37.160
Every time I want to look at the len function anywhere, I first need to check the global namespace and that's going to be a failed lookup.

00:40:37.160 --> 00:40:40.560
Then I need to check the built-ins dictionary and that's going to be a successful lookup.

00:40:40.560 --> 00:40:47.800
So every time I want to use len or range or list or any of those built-ins, that's the cost that I have to pay.

00:40:47.800 --> 00:40:50.740
But people don't change the global namespace that often.

00:40:50.740 --> 00:40:55.700
And people change the built-ins namespace even less often, or at least they shouldn't be changing it very often.

00:40:55.700 --> 00:40:58.060
I'm going to make false true and true false.

00:40:58.060 --> 00:40:58.980
Let's see what that is.

00:41:00.440 --> 00:41:11.480
And so you can make these observations where it's like, okay, well, if the set of keys in the global namespace hasn't changed since last time this bytecode instruction ran, then I know that that lookup is going to fail.

00:41:11.480 --> 00:41:15.800
Because if it failed last time and the keys are the same, then it's going to fail this time as well.

00:41:15.800 --> 00:41:16.740
So we can just skip that.

00:41:16.740 --> 00:41:19.240
And same for the built-ins dictionary.

00:41:19.240 --> 00:41:26.480
You know, if we know that the keys in that dictionary haven't changed, that actually means that the internal layout of the dictionary is the same.

00:41:26.480 --> 00:41:30.840
And we don't even need to look up len in the built-ins dictionary.

00:41:30.840 --> 00:41:35.420
We can reach directly to the last location where it was before and give you that instead.

00:41:35.420 --> 00:41:41.680
And so you often see in a lot of code as like an older code as a kind of a micro-optimization.

00:41:41.680 --> 00:41:54.260
Whenever someone was using a built-in in like a very hot Python loop, sometimes you'd see them like do this kind of quark trick where they make it a local variable by saying like len equals len or something like that as part of the function's arguments.

00:41:54.380 --> 00:41:56.960
So that you turn it into a fast local load.

00:41:56.960 --> 00:42:02.680
And what we've essentially done is, you know, made ugly acts like that totally unnecessary.

00:42:02.680 --> 00:42:03.200
Yeah.

00:42:03.200 --> 00:42:03.620
Which is really cool.

00:42:03.620 --> 00:42:05.120
Do that behind the scenes transparently.

00:42:05.120 --> 00:42:05.500
Yeah.

00:42:05.500 --> 00:42:05.940
Exactly.

00:42:05.940 --> 00:42:08.120
And so that's just, you know, one example.

00:42:08.120 --> 00:42:15.520
We've done tons of specializations for all sorts of things, ranging from calls to attribute lookups to attribute stores, etc.

00:42:15.720 --> 00:42:18.880
So, yeah, it's a really, really powerful thing.

00:42:18.880 --> 00:42:20.340
What was it?

00:42:20.340 --> 00:42:22.420
It's the 569?

00:42:22.420 --> 00:42:23.680
Yeah, Mark wrote it.

00:42:23.680 --> 00:42:24.460
It was 659.

00:42:24.460 --> 00:42:25.300
659.

00:42:25.300 --> 00:42:26.100
Almost there.

00:42:26.100 --> 00:42:26.320
Yeah.

00:42:26.320 --> 00:42:26.780
Yeah.

00:42:26.880 --> 00:42:28.940
So this interpreter is Mark's baby.

00:42:28.940 --> 00:42:30.680
He could tell you much more about it than I could.

00:42:30.680 --> 00:42:30.960
Yeah.

00:42:30.960 --> 00:42:33.140
I just want to give you a chance to give a shout out about specialist.

00:42:33.140 --> 00:42:33.820
Yeah.

00:42:33.820 --> 00:42:34.140
Yeah.

00:42:34.140 --> 00:42:36.040
So this is why I was on your show a couple of weeks ago.

00:42:36.040 --> 00:42:39.720
So looking at bytecode disassemblies is not fun.

00:42:40.020 --> 00:42:46.680
And so one thing that's kind of cool is, you know, if you upgrade to Python 3.11, you run your code and you saw it got, you know, 10, 20, 30% faster.

00:42:46.680 --> 00:42:49.660
You might be wondering, like, okay, where did it get faster?

00:42:49.660 --> 00:42:51.640
Like, what is faster about my code?

00:42:51.640 --> 00:42:55.680
And so specialist is basically a package that I made.

00:42:55.680 --> 00:42:56.600
It's pip installable.

00:42:56.600 --> 00:42:57.760
It only works on 3.11.

00:42:58.180 --> 00:43:14.820
And basically, if you run your code using specialist instead of Python, so you just type specialist myproject.py or whatever, it will open a web browser and show you your code, but color highlighted to show you where the interpreter was able to specialize your code, where it wasn't.

00:43:14.820 --> 00:43:16.080
And that's really neat.

00:43:16.080 --> 00:43:19.700
So you can see, like, oh, actually, you know, these are the attribute loads that got faster.

00:43:19.700 --> 00:43:22.340
These are the places where my global loads are being cached.

00:43:22.340 --> 00:43:23.600
That's awesome.

00:43:23.600 --> 00:43:24.860
Yeah, this is a really cool project.

00:43:24.860 --> 00:43:30.520
And it has some proactive features, not just informational aspects, I think, anyway.

00:43:30.520 --> 00:43:38.260
You know, if you run a profiler, it'll show you where your code's spending time, but it doesn't mean you should go change everything to make it faster.

00:43:38.260 --> 00:43:46.900
You should look at, like, oh, this loop or this one function is, like, the thing that maybe we should think about slightly changing the algorithm or the way we do a loop or something.

00:43:46.900 --> 00:43:52.720
And it's a little bit similar here because the specializing adaptive interpreter only specializes some things.

00:43:52.860 --> 00:43:58.140
Like, it doesn't specialize floats interacting with ints or those types of things.

00:43:58.140 --> 00:44:00.080
Or I think division as well.

00:44:00.080 --> 00:44:04.020
And so there's certain ways you might be able to slightly change inside of a really hot loop.

00:44:04.020 --> 00:44:08.740
You know, make something to float ahead of time if you know it's going to be involved in floating point operations.

00:44:08.740 --> 00:44:09.280
Right.

00:44:09.280 --> 00:44:09.720
Yeah.

00:44:10.680 --> 00:44:15.840
The idea is that this is show us how we can fix things so that you don't need to mess with your code.

00:44:15.840 --> 00:44:17.320
I see.

00:44:17.320 --> 00:44:19.040
So this is in the future.

00:44:19.040 --> 00:44:19.480
Okay.

00:44:19.480 --> 00:44:19.780
Yeah.

00:44:19.780 --> 00:44:20.040
Awesome.

00:44:20.040 --> 00:44:20.300
Yeah.

00:44:20.300 --> 00:44:27.480
I would not necessarily encourage people to start tuning individual bytecode instructions in their code due to our implementation details.

00:44:27.480 --> 00:44:29.320
Otherwise, you will end coding in C.

00:44:29.400 --> 00:44:32.940
You all mean I need to, I got to take all those decimal points back out of my code.

00:44:32.940 --> 00:44:33.420
No, just kidding.

00:44:33.420 --> 00:44:33.680
Yeah.

00:44:33.680 --> 00:44:35.940
I want to get every single bytecode instruction green.

00:44:35.940 --> 00:44:38.120
Some things will never specialize.

00:44:38.120 --> 00:44:40.020
And that's just an artifact of programs.

00:44:40.020 --> 00:44:45.200
But, you know, if we can specialize enough, and we typically do, you know, one line, maybe 20 bytecode instructions.

00:44:45.200 --> 00:44:51.520
If, you know, four of them get specialized successfully and two of them don't, generally, that will still be faster.

00:44:51.520 --> 00:44:54.100
Brian, do you know what you should do for April Fool?

00:44:54.100 --> 00:45:00.120
Like, you should do a pytest plugin that shows you the percentage of specialized instructions in your code.

00:45:00.120 --> 00:45:02.100
And people can fix the percentage.

00:45:02.100 --> 00:45:06.700
So they can say, fail my test suite if my code is not specialized more than 50%.

00:45:06.700 --> 00:45:10.660
If you de-specialize it, it's like a performance regression.

00:45:10.660 --> 00:45:11.780
Drop it.

00:45:11.780 --> 00:45:11.960
Yeah.

00:45:11.960 --> 00:45:12.880
Yeah.

00:45:12.880 --> 00:45:14.020
It's like a coverage thing.

00:45:14.020 --> 00:45:14.220
Yeah.

00:45:14.220 --> 00:45:16.200
No, I was kind of thinking about this.

00:45:16.200 --> 00:45:17.980
So Paulo can tell you more about this.

00:45:17.980 --> 00:45:29.880
But his cool new tracebacks, the whole reason Specialist is able to do these cool, you know, column level highlighting of your source code is because we do have that fine-grained position information under the hood.

00:45:29.880 --> 00:45:34.000
So we kind of just piggybacked on that feature in order to give you that.

00:45:34.140 --> 00:45:41.860
But I was kind of thinking another thing, another April Fool's project could be, you know, column level coverage information.

00:45:41.860 --> 00:45:44.620
So to get to 100% coverage, you have to cover every single column.

00:45:44.620 --> 00:45:44.980
Exactly.

00:45:44.980 --> 00:45:45.440
Yeah, yeah.

00:45:45.440 --> 00:45:47.380
I feel like people might take that too seriously.

00:45:47.380 --> 00:45:48.500
Even the white space.

00:45:48.500 --> 00:45:49.860
Oh, this white space is not covered.

00:45:49.860 --> 00:45:51.540
Yeah.

00:45:51.540 --> 00:45:53.860
You think you're intense by having branch coverage turned on.

00:45:53.860 --> 00:45:55.340
Just wait till you have column coverage turned on.

00:45:55.340 --> 00:45:55.540
Yeah.

00:45:55.540 --> 00:45:57.880
You can only cover two white spaces per line.

00:45:57.880 --> 00:45:59.040
So you got to call that a lot.

00:45:59.240 --> 00:45:59.540
All right.

00:45:59.540 --> 00:46:06.220
I think that's a perfect segue over to one of the most tangible contributions from Pablo here.

00:46:06.220 --> 00:46:10.120
Maybe tell us about this new fine-grained error locations and tracebacks.

00:46:10.120 --> 00:46:10.980
This is fantastic.

00:46:10.980 --> 00:46:17.900
This will save people being in debuggers or rewriting their code with tons of parent statements to figure out what's going on, I think.

00:46:17.900 --> 00:46:18.180
Yeah.

00:46:18.180 --> 00:46:18.840
Thank you very much.

00:46:18.840 --> 00:46:20.840
We put a lot of effort into this.

00:46:21.520 --> 00:46:24.840
So this is, man, I don't even remember my pep, so I don't know.

00:46:24.840 --> 00:46:27.700
It's PEP something something, and it has a horrendous name.

00:46:27.700 --> 00:46:30.280
Six, five, seven, and let's see.

00:46:30.280 --> 00:46:31.040
Six, five, seven.

00:46:31.040 --> 00:46:31.560
Thanks.

00:46:31.560 --> 00:46:34.820
Let's include fine-grained error locations and tracebacks.

00:46:34.820 --> 00:46:36.080
Yeah, the worst name.

00:46:36.080 --> 00:46:42.180
I think I was talking with Mark in the Python code of press print, and he was saying, like, what it means, like, fine-grained.

00:46:42.180 --> 00:46:45.040
Like, you know, like, is this very fine-grained?

00:46:45.040 --> 00:46:48.180
Like, so I think we are renaming the PEP to fancy tracebacks.

00:46:48.180 --> 00:46:49.720
I think that's much better.

00:46:50.560 --> 00:46:55.820
Anyway, so this is a project I worked together with Batuhan, Tazkaya, and Omar Azkar.

00:46:55.820 --> 00:46:59.180
So kudos to them as well, because they participated equally on this.

00:46:59.180 --> 00:47:08.100
And the idea is that we were, like, we started this project to make, you know, to improve the error messages in the interpreter and the general experience.

00:47:08.100 --> 00:47:14.320
Not only for, you know, people, because when people talk about this, they normally refer to people starting to learn Python.

00:47:14.320 --> 00:47:18.100
But, like, to be honest, most of these things also affect people that are experts.

00:47:18.240 --> 00:47:24.980
Like, I always say that when I implemented the suggestions, I was the first one benefiting from them because, like, I make a lot of typos.

00:47:24.980 --> 00:47:26.540
And, you know, like, this is odd.

00:47:26.540 --> 00:47:27.240
You mean this?

00:47:27.860 --> 00:47:34.620
So the idea that we have is that most of the time, the lack of, you know, the interpreter shows you kind of the position when the error happens.

00:47:34.620 --> 00:47:44.100
But it's quite limited because most of the time people tend to have, due to Python flexible syntax, a huge amount of, like, complexity, even in a single line.

00:47:44.100 --> 00:47:46.140
In the pep, there is a bunch of examples.

00:47:46.140 --> 00:47:52.760
Like, you access a bunch of keys in a dictionary and some of them doesn't work or it's not there or it's none or something like that.

00:47:52.760 --> 00:47:52.900
Right.

00:47:52.900 --> 00:47:54.140
And then it fails.

00:47:54.140 --> 00:47:58.080
Or sometimes you have, like, several function calls or several additions.

00:47:58.580 --> 00:48:00.400
And, you know, it's quite difficult.

00:48:00.400 --> 00:48:11.160
And most of the time fixing these things involve going into a debugger like PDB and then trying to inspect every single object and say, okay, this dictionary doesn't have this key at this level.

00:48:11.320 --> 00:48:12.620
And, like, you know, that sucks.

00:48:12.620 --> 00:48:13.440
Like, it's not.

00:48:13.440 --> 00:48:13.700
Yeah.

00:48:13.700 --> 00:48:17.980
Because, like, the buggers are cool, but, like, it's cooler not to use them.

00:48:17.980 --> 00:48:18.260
Right.

00:48:18.260 --> 00:48:21.340
And, you know, we thought, what can we do here?

00:48:21.340 --> 00:48:26.360
And we arrived to this idea, actually, also to mention everyone involved.

00:48:26.360 --> 00:48:37.620
This was originally inspired by some kind of prototype that Carl from the PiPi team made very long ago when he saw, like, a kind of minimal version of this.

00:48:37.620 --> 00:48:39.900
And then I said, okay, can we do this?

00:48:40.080 --> 00:48:48.580
And what we do now is that we propagate because the parser, our super cool PEG parser, knows position of all the tokens and things like that.

00:48:48.580 --> 00:48:52.400
So we are propagating that information through the interpreter.

00:48:52.400 --> 00:48:55.860
And we store this information now in code objects.

00:48:55.860 --> 00:48:59.520
So a side effect of this PEG actual is that code objects are slightly bigger.

00:48:59.520 --> 00:49:05.180
Although, you know, because code objects don't tend to be a huge percentage of your application, it doesn't really matter that much.

00:49:05.180 --> 00:49:06.720
Maybe PYC files are a bit bigger.

00:49:06.820 --> 00:49:10.020
But, you know, you have a lot of disk space, I'm sure.

00:49:10.020 --> 00:49:13.920
And the idea is that, you know, we store this information in code objects.

00:49:13.920 --> 00:49:19.080
So when you raise an exception, we say, well, what is the instruction that raised this exception?

00:49:19.320 --> 00:49:26.960
And then once we know which is the instruction that raised the exception, then we go and say, okay, what is the position information that generated this instruction?

00:49:26.960 --> 00:49:28.800
And because we propagated it, we know.

00:49:28.800 --> 00:49:35.080
And then we can say, okay, here is kind of like the lines, the columns that this instruction spans.

00:49:35.260 --> 00:49:39.120
So that kind of allows us to underline the specific location.

00:49:39.120 --> 00:49:40.320
Yeah, but we go a bit further.

00:49:40.320 --> 00:49:41.860
Sorry, sorry, go ahead, Michael.

00:49:41.860 --> 00:49:43.800
I was going to say, this is super valuable.

00:49:43.800 --> 00:49:51.460
The example you have in the PEP is you have a dictionary, you say bracket of key A, and then the thing that comes back is another dictionary.

00:49:51.460 --> 00:49:55.020
So you say bracket B, and then another dictionary, bracket C, and then bracket D.

00:49:55.020 --> 00:50:06.900
And if, you know, in 3.10, the error is just like, if one of those is none, say none type is object is not subscriptable, or maybe, you know, does not contain that key or some weird thing like that.

00:50:06.900 --> 00:50:09.020
But is it A, B, C, or D?

00:50:09.020 --> 00:50:09.860
You have no idea.

00:50:09.860 --> 00:50:12.500
You're in a debugger printing them out separately or something.

00:50:12.500 --> 00:50:14.760
But now it just goes, nope, it's the C one.

00:50:14.760 --> 00:50:17.720
That's, it's the third subscript one.

00:50:17.720 --> 00:50:19.380
And that's just, just jump right to it.

00:50:19.380 --> 00:50:19.780
Oh, okay.

00:50:19.780 --> 00:50:22.680
Yeah, also this error, none type is not subscriptable.

00:50:22.680 --> 00:50:25.120
It's kind of like, thanks for the info.

00:50:25.120 --> 00:50:27.480
Like, it's like, you know, water is wet.

00:50:27.480 --> 00:50:28.460
Okay, thanks.

00:50:28.460 --> 00:50:30.240
It's not super useful.

00:50:30.240 --> 00:50:30.980
No, exactly.

00:50:30.980 --> 00:50:32.280
So tell me when it's going to rain.

00:50:32.280 --> 00:50:34.160
Anyway, we did like the first version of this.

00:50:34.160 --> 00:50:39.080
And then we realized, realized that there was some kind of like, you know, it was cool.

00:50:39.080 --> 00:50:45.820
Like most people really like it, but like, especially for instance, with the example, with the dictionary that has many dictionaries inside.

00:50:45.820 --> 00:50:49.500
There was some confusion because like, you know, it underlines the whole thing.

00:50:49.720 --> 00:50:58.120
And then, you know, the order of operations and, you know, also with complex mathematical expressions, like you do A plus B plus C and the last addition fails.

00:50:58.120 --> 00:51:05.760
It needs to underline A plus B plus C because what happened is that it first added A plus B and that gives you something that then you added to C.

00:51:05.760 --> 00:51:10.140
And what happened is that the last addition failed, but that includes A plus B.

00:51:10.140 --> 00:51:11.440
So you need to underline the whole thing.

00:51:11.440 --> 00:51:18.480
If you know the order of operations and I just underline A plus B plus C, you know that what will fail is the last one.

00:51:18.620 --> 00:51:20.320
Because that's the last one that is executed.

00:51:20.320 --> 00:51:28.120
But it's still confusing because, you know, specifically also with the dictionary, people were saying, yeah, okay, but like you're underlining three keys here, which is the one that failed.

00:51:28.120 --> 00:51:33.240
I mean, you know, you can learn by experience that is the last one, but it's kind of like, it was not a great experience.

00:51:33.240 --> 00:51:35.100
So we went a step farther.

00:51:35.160 --> 00:51:43.620
So what we do is that once we know the kind of range in the line that shows the problem, we reparse that chunk of expression.

00:51:43.620 --> 00:51:47.000
And then we know, okay, so we know now that this expression has this AST.

00:51:47.000 --> 00:51:48.900
And then we analyze the AST.

00:51:48.900 --> 00:51:54.240
And then we say, okay, is this AST something that we can further improve the error message?

00:51:54.380 --> 00:52:03.000
Like, for instance, is this AST a bunch of key access in a dictionary or a bunch of attribute access or a bunch of function calls or maybe binary operations?

00:52:03.000 --> 00:52:10.620
And if it's the case, then we use a specialized, like, you know, underline, I don't know, tildes or squiggles or whatever it's called.

00:52:10.620 --> 00:52:11.060
Yeah.

00:52:11.060 --> 00:52:19.020
And, you know, the dictionary ones have this different one that marks which key access it was known, the same thing for binary operations and things like that.

00:52:19.020 --> 00:52:30.900
So we do this extra step at the end that, you know, does a bunch of extra work, but it tries to improve even upon the kind of just underlining the line just so we can offer even more rich information.

00:52:30.900 --> 00:52:32.520
And I'm quite happy.

00:52:32.520 --> 00:52:33.920
I'm very pleased about this.

00:52:33.920 --> 00:52:37.520
Sorry, Mark, but I think it's the best feature of 3.11.

00:52:38.440 --> 00:52:41.840
Yeah, this is probably the second stream when I said this, but it's true.

00:52:41.840 --> 00:52:43.360
Totally, totally true.

00:52:43.360 --> 00:52:44.120
100% true.

00:52:44.120 --> 00:52:45.600
So I'm very excited about this.

00:52:45.600 --> 00:52:46.920
I literally use this every day.

00:52:46.920 --> 00:52:48.800
Today I was deploying Python 3.11.

00:52:48.800 --> 00:52:50.040
Well, this week, sorry.

00:52:50.040 --> 00:52:53.060
I was deploying Python 3.11 at Bloomberg and something went wrong.

00:52:53.060 --> 00:52:55.060
And literally, this thing saved my day.

00:52:55.060 --> 00:52:59.280
This saved me to just logging into some forsaken machine and understanding what's going on.

00:52:59.280 --> 00:53:00.280
What about that?

00:53:00.280 --> 00:53:01.380
So super cool.

00:53:01.380 --> 00:53:01.880
Very happy.

00:53:01.880 --> 00:53:06.500
I hope that everybody that uses this and is happy reached to us and say, I'm happy.

00:53:06.680 --> 00:53:09.920
Because normally people reach to us when they are not happy.

00:53:09.920 --> 00:53:12.740
And they say, evil core developers, you break everything.

00:53:12.740 --> 00:53:15.660
But instead of that, you should reach to us and say, nice.

00:53:15.660 --> 00:53:18.240
I did this cool thing.

00:53:18.240 --> 00:53:20.520
You should tweet at Pablo or something, though.

00:53:20.520 --> 00:53:22.440
Don't open issues saying you're happy.

00:53:22.440 --> 00:53:22.860
Exactly.

00:53:24.080 --> 00:53:28.320
Just tweet a couple of tildes, a few carrots, and a smiley face at him.

00:53:28.320 --> 00:53:28.620
Exactly.

00:53:28.620 --> 00:53:30.440
Tweet happy at python.org.

00:53:30.440 --> 00:53:32.920
I will take that email address.

00:53:32.920 --> 00:53:33.460
Awesome.

00:53:33.460 --> 00:53:34.400
It is that.

00:53:34.400 --> 00:53:36.080
We improve it a bit further.

00:53:36.080 --> 00:53:40.360
One of the things that happen is that, you know, like sometimes if the whole line is wrong,

00:53:40.360 --> 00:53:44.160
because this example you have there, if you, sorry, for the ones listening to the podcast,

00:53:44.360 --> 00:53:47.920
we have here some, we are seeing some output, but that doesn't matter.

00:53:47.920 --> 00:53:48.400
Don't worry.

00:53:48.400 --> 00:53:49.320
I will describe it.

00:53:49.320 --> 00:53:53.380
So for instance, you're calling a function and that's the whole thing that is in the line.

00:53:53.380 --> 00:53:55.460
We used to underline the whole thing.

00:53:55.460 --> 00:54:00.580
So we'll say, okay, even if the whole line is failing, so there's not like a part of the line

00:54:00.580 --> 00:54:02.000
is failing, the whole thing is failing.

00:54:02.000 --> 00:54:05.300
We used to underline that and that apparently is still on the PEP.

00:54:05.300 --> 00:54:08.280
Maybe I should change that because that is not like that anymore.

00:54:08.280 --> 00:54:12.260
Because someone suggested, I mean, come on, like if it's the whole line is failing,

00:54:12.260 --> 00:54:14.360
underline the whole line is actually not that useful.

00:54:14.360 --> 00:54:17.400
And you know, you are, you are spending vertical space.

00:54:17.400 --> 00:54:19.040
So you need to scroll a lot.

00:54:19.040 --> 00:54:22.640
And at the beginning I say, yeah, but it's inconsistent.

00:54:22.640 --> 00:54:23.600
I don't like it.

00:54:23.600 --> 00:54:28.080
And I pushed back a bit, but like then, you know, more people say, Pablo, you're wrong.

00:54:28.080 --> 00:54:29.740
And then I say, okay, okay, I'm wrong.

00:54:29.980 --> 00:54:31.260
We improve this further.

00:54:31.260 --> 00:54:34.560
So you say, but don't take this as an advice.

00:54:34.560 --> 00:54:37.140
Don't tell me that I'm wrong collectively, please.

00:54:37.140 --> 00:54:38.740
But right.

00:54:38.740 --> 00:54:43.800
So now if the whole line is underlined, we don't underline it because it doesn't really

00:54:43.800 --> 00:54:45.080
add any new information, right?

00:54:45.080 --> 00:54:49.440
So, so only if a part of the line is contains the error, not the whole line.

00:54:49.440 --> 00:54:54.400
So this means that we are not going to, you know, consume a lot of vertical space for no reason.

00:54:54.400 --> 00:54:58.860
And the last thing I wanted to say is that, you know, there is some people somewhere in the universe

00:54:58.860 --> 00:55:05.180
that may care about that extra disk space on their PYC files, or they just really, really

00:55:05.180 --> 00:55:06.100
hate squiggles.

00:55:06.100 --> 00:55:10.600
I don't know if that is even physically possible, but you know, there are very different and

00:55:10.600 --> 00:55:12.420
diverse set of people.

00:55:12.420 --> 00:55:13.420
You are one of those.

00:55:13.420 --> 00:55:17.340
There is a collection of different ways you can deactivate this feature.

00:55:17.340 --> 00:55:20.660
There is an environment variable with a super long name.

00:55:20.660 --> 00:55:23.660
And there is minus X option when you launch the interpreter.

00:55:23.660 --> 00:55:26.200
So you can say Python minus X, something, something.

00:55:26.200 --> 00:55:27.280
I don't know how it's called.

00:55:27.280 --> 00:55:29.560
I think it's called no the back ranges.

00:55:29.560 --> 00:55:30.620
What about that?

00:55:30.620 --> 00:55:32.080
What an incredible naming.

00:55:32.520 --> 00:55:36.780
And then you set no the back ranges to one and it deactivates the feature.

00:55:36.780 --> 00:55:37.300
Incredible.

00:55:37.300 --> 00:55:38.080
Like magic.

00:55:38.080 --> 00:55:38.640
It's gone.

00:55:38.640 --> 00:55:41.440
And you can reclaim your PYC files.

00:55:41.440 --> 00:55:44.420
And you can even generate PYC files without this information.

00:55:44.420 --> 00:55:48.440
If when you're compiling PYC files, you set this evil variable.

00:55:48.440 --> 00:55:50.180
But don't do that, listeners.

00:55:50.180 --> 00:55:50.780
Don't do that.

00:55:50.780 --> 00:55:51.280
It's evil.

00:55:51.280 --> 00:55:51.880
Don't do that.

00:55:51.880 --> 00:55:52.820
Just use it.

00:55:52.820 --> 00:55:53.460
It's great.

00:55:53.460 --> 00:55:53.720
Yeah.

00:55:54.760 --> 00:56:03.080
There's another kind of type of errors that I think we're going to get is about edge cases where the compiler doesn't get the line numbers right.

00:56:03.080 --> 00:56:07.120
Because all these kind of fine grained locations, it's all new.

00:56:07.120 --> 00:56:09.300
And, you know, we're still ironing out.

00:56:09.300 --> 00:56:10.240
The front future.

00:56:10.240 --> 00:56:14.440
There is a front future, I think, that you put like a bunch of things with the front future.

00:56:14.440 --> 00:56:15.980
It just complains on a random place.

00:56:15.980 --> 00:56:16.340
Yeah.

00:56:16.340 --> 00:56:18.320
Today I found that one.

00:56:18.320 --> 00:56:23.080
But I've been looking at the compiler and line number, location information.

00:56:23.080 --> 00:56:24.440
And it's a bit off here and there.

00:56:24.500 --> 00:56:27.820
And we have received bug reports from other people as well.

00:56:27.820 --> 00:56:29.440
The range here doesn't look right.

00:56:29.440 --> 00:56:31.580
The range here looks too broad.

00:56:31.580 --> 00:56:36.480
So, yeah, we're going to be ironing that out, I guess, for 312s.

00:56:36.480 --> 00:56:36.720
Yeah.

00:56:36.720 --> 00:56:42.560
It's really nice when people are using betas and release candidates, though, because we were able to catch a lot of those before the release.

00:56:42.560 --> 00:56:50.240
Because there were a couple people, I forget exactly the name of the project, but they were working on like a code animation tool where it animates your code while it's running.

00:56:50.240 --> 00:56:53.960
And they were using these new ranges to identify AST nodes and stuff.

00:56:54.160 --> 00:56:58.960
And so they did this thing, I guess, where they like run their tool in the entire standard library and make sure it's correct.

00:56:59.100 --> 00:57:06.100
And so we got a bunch of bug reports that basically said, oh, you know, this column information is off for this weird multi-line attribute access or something.

00:57:06.100 --> 00:57:09.100
If you recall, I think you fixed an error.

00:57:09.100 --> 00:57:15.100
That was super weird because it was like a method access, like, you know, my instance of full.

00:57:15.100 --> 00:57:15.280
Yeah.

00:57:15.280 --> 00:57:20.160
And if the method access has like some like vowel or something like that, it was wrong.

00:57:20.440 --> 00:57:23.000
And if you added some extra letter, it was fine.

00:57:23.000 --> 00:57:35.700
Yeah, it was like if you split your method access across two lines, if you do like x dot method or x dot method or x dot method on three lines or two lines or something.

00:57:35.860 --> 00:57:43.000
The way we trace those lines, we always trace the method when we're actually loading the method, even if it's on a different line.

00:57:43.000 --> 00:57:45.020
It's like where the actual method load started.

00:57:45.020 --> 00:57:48.840
And then we were doing some weird math to like figure out where the dot is.

00:57:48.840 --> 00:57:50.920
So we would try to put it on the same line as the dot.

00:57:51.200 --> 00:57:54.080
So we would just like subtract one from the length of the name.

00:57:54.080 --> 00:57:55.800
So there's all sorts of crazy stuff.

00:57:55.800 --> 00:57:58.520
And that came from the grave because we fixed that.

00:57:58.520 --> 00:58:02.680
And then it was wrong again because like we were like miscalculating the name.

00:58:02.680 --> 00:58:04.780
It's just that easy.

00:58:04.780 --> 00:58:05.480
Oh my goodness.

00:58:05.480 --> 00:58:05.780
Yeah.

00:58:05.780 --> 00:58:07.260
So all sorts of fun stuff like that.

00:58:07.260 --> 00:58:07.560
Yeah.

00:58:07.560 --> 00:58:08.260
Amazing.

00:58:08.260 --> 00:58:12.240
Well, yeah, this is definitely one of the highlight features for sure.

00:58:12.240 --> 00:58:14.120
And also the performance work that you're all doing.

00:58:14.120 --> 00:58:14.400
All right.

00:58:14.400 --> 00:58:16.320
We're getting very, very short on time.

00:58:16.320 --> 00:58:19.120
So I think maybe a super, super lightning round here.

00:58:19.120 --> 00:58:22.200
Let me just say we also got Tomolib support built in.

00:58:22.200 --> 00:58:26.480
We've got the AsyncIO task groups a la Trio Nurseries.

00:58:26.480 --> 00:58:30.960
We've got new features for atomic grouping and regular expressions.

00:58:30.960 --> 00:58:32.480
A self-type.

00:58:32.480 --> 00:58:34.440
A lot of type things have been added.

00:58:34.440 --> 00:58:39.840
So we've got the self-type, bariatric generics, literal strings, which is very interesting.

00:58:39.840 --> 00:58:43.540
 Łukasz did a talk about that on the release live stream.

00:58:43.540 --> 00:58:46.340
Stuff for type dict and data class transformations.

00:58:46.340 --> 00:58:47.760
So great stuff.

00:58:47.980 --> 00:58:50.760
Now, let's just really quickly round out.

00:58:50.760 --> 00:58:54.700
What's the Python 3.11 story for PyScript, Pyodide?

00:58:54.700 --> 00:58:57.500
Is there, do you know, have anyone out there know?

00:58:57.500 --> 00:58:58.260
I don't know.

00:58:58.260 --> 00:58:59.180
I suppose it works.

00:58:59.180 --> 00:59:03.880
I think WebAssembly is now a tier two or tier three supported platform, right?

00:59:03.880 --> 00:59:08.380
So he has been making a lot of improvements to the build process, which, you know, is not easy.

00:59:08.540 --> 00:59:10.560
So kudos to Christian Himes.

00:59:10.560 --> 00:59:11.900
If you're listening, you're great.

00:59:12.460 --> 00:59:16.600
I suppose that PyScript can, through Pyodide.

00:59:16.600 --> 00:59:18.340
This is how many layers is this?

00:59:18.340 --> 00:59:24.980
So Pyodide through this can leverage all these improvements because I don't know how the whole

00:59:24.980 --> 00:59:26.660
layer tower thing is working.

00:59:26.980 --> 00:59:31.580
But Pyodide has a bunch of patches that, you know, you need to modify CPython so it builds

00:59:31.580 --> 00:59:33.580
nicely on WebAssembly platforms.

00:59:33.580 --> 00:59:34.940
I don't know the details on that.

00:59:34.940 --> 00:59:37.260
I just know that some of them are okayish.

00:59:37.260 --> 00:59:39.660
Some of them are not okay and quite difficult to maintain.

00:59:39.660 --> 00:59:45.080
And Christian Himes has been making a lot of great effort to, you know, change here and there

00:59:45.080 --> 00:59:48.260
and like put a lot of macros and if devs and things like that.

00:59:48.260 --> 00:59:50.700
So CPython kind of builds easier.

00:59:50.700 --> 00:59:57.440
This probably translates that Pyodide, I hope, kind of, you know, can consume this build in

00:59:57.440 --> 00:59:58.500
an easier way with less patches.

00:59:58.500 --> 01:00:04.020
And I suppose that translates into PyScript, like just using the Pyodide thing easier.

01:00:04.020 --> 01:00:09.760
But yeah, I don't think that there is a huge amount of improvements more than, you know,

01:00:09.760 --> 01:00:13.140
we are working towards official support as Bram was mentioning.

01:00:13.140 --> 01:00:14.920
We have this next year system.

01:00:14.920 --> 01:00:15.680
It's super cool.

01:00:15.680 --> 01:00:21.000
And as like an unrelated fun fact, Mike Drapu, one of the early developers of Pyodide, is

01:00:21.000 --> 01:00:22.840
actually managing our team at Microsoft.

01:00:22.840 --> 01:00:27.100
Oh, it's funny how the circle comes back around indeed.

01:00:27.100 --> 01:00:28.580
How the dorm tables.

01:00:28.580 --> 01:00:30.700
That's right.

01:00:30.700 --> 01:00:31.780
All right.

01:00:31.780 --> 01:00:34.700
We are out of time, but super exciting.

01:00:34.700 --> 01:00:36.500
I wish we had some champagne.

01:00:36.500 --> 01:00:39.700
And Pablo, we didn't even bring hats to celebrate Python 3.11.

01:00:39.700 --> 01:00:42.100
But I know everyone out there is extremely excited.

01:00:42.100 --> 01:00:44.120
I cannot see it, but I have a Python 3.11.

01:00:44.120 --> 01:00:44.960
Yes.

01:00:44.960 --> 01:00:45.240
Yeah.

01:00:45.240 --> 01:00:47.960
That's a great new logo for 3.11 and stuff.

01:00:47.960 --> 01:00:49.900
Not for in general, but just for the release.

01:00:49.900 --> 01:00:50.440
It's awesome.

01:00:50.440 --> 01:00:50.920
All right.

01:00:50.920 --> 01:00:54.660
Before we get out of here, let me just ask you one final question and then we'll call it

01:00:54.660 --> 01:00:55.000
a show.

01:00:55.000 --> 01:00:56.580
Notable PyPI package.

01:00:56.580 --> 01:00:57.760
Something you want to give a shout out to.

01:00:57.760 --> 01:00:59.860
We'll go top to bottom in the picture here.

01:00:59.860 --> 01:01:00.220
Pablo?

01:01:00.220 --> 01:01:01.760
Notable PyPI package.

01:01:02.260 --> 01:01:02.700
Yeah.

01:01:02.700 --> 01:01:02.700
Yeah.

01:01:02.700 --> 01:01:02.800
Yeah.

01:01:02.800 --> 01:01:03.660
Some library.

01:01:03.660 --> 01:01:05.680
And I'm going to say memory.

01:01:05.680 --> 01:01:06.600
Use memory.

01:01:06.600 --> 01:01:09.140
The one and only Python memory profiler.

01:01:09.140 --> 01:01:09.560
Yeah.

01:01:09.560 --> 01:01:12.800
Solve your problems on production today with memory.

01:01:12.800 --> 01:01:15.020
That and the underlying errors, you'll be all good.

01:01:15.020 --> 01:01:15.380
Exactly.

01:01:15.380 --> 01:01:15.700
Yeah.

01:01:15.700 --> 01:01:16.300
A combination.

01:01:16.300 --> 01:01:19.140
Arit, how are you?

01:01:19.280 --> 01:01:23.700
Well, I've had some interaction with the author of bytecode recently because I was looking

01:01:23.700 --> 01:01:28.100
at things to do in the testing and in the interpreter that are kind of like that.

01:01:28.100 --> 01:01:33.600
So this is a library you can kind of from Python write bytecode and it's pretty neat.

01:01:33.600 --> 01:01:38.140
And it's struggling with zero cost exceptions, but that's what it is.

01:01:38.140 --> 01:01:40.580
It's like an inline assembly, but for Python.

01:01:40.580 --> 01:01:41.720
Yeah.

01:01:41.720 --> 01:01:47.100
It's like from a Python script, you can kind of write bit of bytecode and get it to, I

01:01:47.100 --> 01:01:49.140
don't know, do a lot of interesting stuff.

01:01:49.220 --> 01:01:49.660
That's awesome.

01:01:49.660 --> 01:01:50.600
Brent, how about you?

01:01:50.600 --> 01:01:54.480
Well, I'm partial towards specialists, but if I had to choose something else, I, speaking

01:01:54.480 --> 01:01:57.000
of speed, I really like the scaling profiler.

01:01:57.000 --> 01:02:00.900
I've been using it a lot of my own projects and it's awesome.

01:02:00.900 --> 01:02:03.340
I don't know how it's memory profiling compares to memory.

01:02:03.340 --> 01:02:09.140
I'm sure memory is better, but scaling is really nice for measuring the performance across

01:02:09.140 --> 01:02:10.820
both Python and C code, which is cool.

01:02:10.820 --> 01:02:11.140
Excellent.

01:02:11.140 --> 01:02:11.760
Mark?

01:02:11.760 --> 01:02:13.540
Well, it's not actually a PyPI package.

01:02:13.540 --> 01:02:17.560
I was going to say the sys module, which is like pretty much the most fundamental module

01:02:17.560 --> 01:02:18.080
I'm going on.

01:02:18.180 --> 01:02:20.740
There's all sorts of fun things in there.

01:02:20.740 --> 01:02:23.740
You can change the recursion limit and C, you can muddle it.

01:02:23.740 --> 01:02:27.220
If you're interested in how Python works, it's actually quite a sort of fun thing to play

01:02:27.220 --> 01:02:27.440
with.

01:02:27.440 --> 01:02:29.760
Thank you all for all the hard work.

01:02:29.760 --> 01:02:33.720
And I know there are many people who did a ton of work as well who are not on the show

01:02:33.720 --> 01:02:35.480
here, but you can represent them as well.

01:02:35.560 --> 01:02:37.080
Thanks all for being here.

01:02:37.080 --> 01:02:38.300
Final call to action.

01:02:38.300 --> 01:02:39.540
People want to get started at 3.11.

01:02:39.540 --> 01:02:40.600
What do you tell them?

01:02:40.600 --> 01:02:42.600
Is it ready for them to get going?

01:02:42.600 --> 01:02:43.400
What do you think?

01:02:43.400 --> 01:02:44.020
It's awesome.

01:02:44.020 --> 01:02:44.660
It's awesome.

01:02:44.660 --> 01:02:49.740
And also now 3.11 comes with a bunch of wheels for all your packages because there has been

01:02:49.740 --> 01:02:54.060
a lot of good work in the people of third-party libraries.

01:02:54.300 --> 01:03:00.140
And now that people are using cibuildwheel, 3.11 was released with wheels for NumPy and

01:03:00.140 --> 01:03:04.880
Pandas and a bunch of other things that previously was failing massively because nobody could compile

01:03:04.880 --> 01:03:06.360
them on their crappy laptop.

01:03:06.360 --> 01:03:07.620
But now you don't need that.

01:03:07.620 --> 01:03:09.320
You can just download them and it works.

01:03:09.320 --> 01:03:10.340
So just use 3.11.

01:03:10.340 --> 01:03:11.180
There is no reason.

01:03:11.180 --> 01:03:12.080
Yeah, that's excellent.

01:03:12.080 --> 01:03:12.560
That's just boring.

01:03:12.560 --> 01:03:13.440
That would be a reason.

01:03:13.540 --> 01:03:16.320
If you're boring and you don't want to use 3.11, then don't use it.

01:03:16.320 --> 01:03:17.300
You didn't break anything.

01:03:17.300 --> 01:03:18.360
Not even a package.

01:03:18.360 --> 01:03:19.540
Much less GitHub.

01:03:19.540 --> 01:03:20.460
Right.

01:03:20.460 --> 01:03:22.620
And we need more benchmarks.

01:03:22.620 --> 01:03:24.180
Well, that's true.

01:03:24.180 --> 01:03:25.100
Yeah, absolutely.

01:03:25.100 --> 01:03:27.220
That's how people can help us make things faster.

01:03:27.220 --> 01:03:27.960
There's more benchmarks.

01:03:27.960 --> 01:03:34.000
There's a standard Python performance suite, but it's kind of a bunch of toy programs and

01:03:34.000 --> 01:03:34.400
so on.

01:03:34.400 --> 01:03:40.100
So if you've got something that might make a nice sort of benchmark, self-contained but

01:03:40.100 --> 01:03:42.540
sort of realistic program, then let us know.

01:03:42.540 --> 01:03:42.880
All right.

01:03:42.880 --> 01:03:43.260
Cool.

01:03:43.340 --> 01:03:44.100
Well, thanks again.

01:03:44.100 --> 01:03:44.920
Great work on it.

01:03:44.920 --> 01:03:47.800
Cam Geerlock out in the audience says, yay, CI Buildwheel.

01:03:47.800 --> 01:03:48.740
Yeah, absolutely.

01:03:48.740 --> 01:03:49.460
Great stuff.

01:03:49.460 --> 01:03:51.020
So thanks again, everyone.

01:03:51.020 --> 01:03:53.940
I'm super excited to start using 3.11 myself.

01:03:53.940 --> 01:03:55.780
Thank you, Michael, for inviting us.

01:03:55.780 --> 01:03:56.900
Yeah, it's great to have you here.

01:03:56.900 --> 01:03:57.280
Thank you.

01:03:57.280 --> 01:03:57.660
Thank you.

01:03:57.660 --> 01:03:58.000
Bye, all.

01:03:58.000 --> 01:04:01.560
I hope you enjoyed this crossover Talk Python episode.

01:04:01.560 --> 01:04:06.520
If you did, please consider subscribing to Talk Python To Me if you don't already do so.

01:04:06.520 --> 01:04:10.440
On behalf of myself and Brian Okken, thanks for being part of Python Bytes.

01:04:10.440 --> 01:04:11.400
Bye now.