WEBVTT

00:00:00.001 --> 00:00:05.280
Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.

00:00:05.280 --> 00:00:10.180
This is episode 330, recorded April 4th, 2023.

00:00:10.180 --> 00:00:11.220
I'm Michael Kennedy.

00:00:11.220 --> 00:00:12.380
And I'm Brian Okken.

00:00:12.380 --> 00:00:15.740
And you can connect with us over on Fosstodon.

00:00:15.740 --> 00:00:18.300
If you're on Mastodon, find us there.

00:00:18.300 --> 00:00:20.640
I'm at mkennedy at fosstodon.org.

00:00:20.640 --> 00:00:22.400
Brian's Brian Okken over there.

00:00:22.400 --> 00:00:24.800
And the show is at Python Bytes at fosstodon.org.

00:00:25.520 --> 00:00:31.060
And if you're interested in the video version, check out pythonbytes.fm/live.

00:00:31.060 --> 00:00:31.680
Click that.

00:00:31.680 --> 00:00:32.740
Go over to the YouTube channel.

00:00:32.740 --> 00:00:33.140
Subscribe.

00:00:33.140 --> 00:00:33.920
Get notified.

00:00:33.920 --> 00:00:37.460
You'll get a little pop-up when we start streaming live.

00:00:37.460 --> 00:00:39.040
It's always fun to be part of it.

00:00:39.040 --> 00:00:41.980
We encourage people to check the show out that way as well.

00:00:41.980 --> 00:00:47.680
So, Brian, let's start off with something that has been almost exactly one year in the works.

00:00:47.680 --> 00:00:50.580
I was just going to ask you about that.

00:00:50.580 --> 00:00:55.220
So, was this about a year ago we talked about this, Pydantic?

00:00:55.260 --> 00:01:09.660
I think I saw something on Twitter, of all places, from Samuel Colvin saying it was April 4th, 2022, that I started working on Pydantic version 2.

00:01:09.660 --> 00:01:11.340
So, that sounds like to the day.

00:01:11.340 --> 00:01:11.840
Okay.

00:01:11.840 --> 00:01:16.740
Well, it's not completely here yet, but it's here enough to try.

00:01:16.740 --> 00:01:18.160
So, I'm pretty excited about it.

00:01:18.160 --> 00:01:22.180
So, Pydantic V2 version 2 pre-release.

00:01:22.180 --> 00:01:24.820
So, people can, it's available now.

00:01:24.820 --> 00:01:26.360
So, people can install it.

00:01:26.360 --> 00:01:32.360
You have to do the, like the install --pre Pydantic.

00:01:32.620 --> 00:01:39.760
And then you can say Pydantic greater than or equal to 2.0 A1, I guess, if you want to get the alpha one or better.

00:01:39.760 --> 00:01:41.900
So, the big news is alpha one's available.

00:01:41.900 --> 00:01:44.400
And it's pretty exciting.

00:01:44.400 --> 00:01:46.940
There's a whole bunch of great stuff changes.

00:01:46.940 --> 00:01:48.680
We've talked, I think we talked about it.

00:01:48.680 --> 00:01:50.340
You talked about it on your show, I think also.

00:01:50.340 --> 00:01:50.520
Yeah.

00:01:50.520 --> 00:01:51.120
Yeah.

00:01:51.120 --> 00:01:57.360
But the headlines here is, well, one, it's not complete yet.

00:01:57.360 --> 00:01:58.100
This is the alpha.

00:01:58.100 --> 00:01:59.540
We're not even debated yet.

00:01:59.540 --> 00:02:05.840
So, if you see, if you try it out and you see something, they've got a GitHub, created a GitHub issue.

00:02:05.840 --> 00:02:13.100
And they want to have people use the bug V2 label to create issues around the version 2.

00:02:13.100 --> 00:02:15.060
Because they want to hop on those right away.

00:02:15.060 --> 00:02:28.480
Anyway, so, the big change was, one of the big changes was to move a lot of Pydantic and the rules and everything into a different module called Pydantic Core.

00:02:28.480 --> 00:02:30.720
That one's mostly written in Rust.

00:02:30.720 --> 00:02:37.980
And so, it's like 5 to 50 times faster overall for performance.

00:02:37.980 --> 00:02:39.220
So, that's pretty exciting.

00:02:39.220 --> 00:02:44.020
I mean, this is, when you're using Pydantic, it's hitting for every interaction, right?

00:02:44.120 --> 00:02:46.240
So, as fast as possible is great.

00:02:46.240 --> 00:03:01.780
And I do like the idea of the, like, the separating the Rust part out into a different module, a different package, Pydantic Core, so that they can have, kind of maintain it and have safety and maintenance around that a little separate.

00:03:01.780 --> 00:03:03.240
I think that makes sense.

00:03:03.240 --> 00:03:03.920
Yeah.

00:03:03.920 --> 00:03:13.200
And people used to have to create their derived classes and put a lot of their customization and their, you know, what's called root level validators and things like that.

00:03:13.300 --> 00:03:16.020
Where it's like, I want to validate the whole class, not just a certain field.

00:03:16.020 --> 00:03:18.620
Or, you know, if this is set, then that has to be set that way.

00:03:18.620 --> 00:03:22.440
Like, a lot of those things had to be done in an OOP way.

00:03:22.440 --> 00:03:27.220
And I think with the Pydantic Core, you have more direct access to, like, a layer below.

00:03:27.400 --> 00:03:34.060
So, it's not just faster, which is fantastic, but it also opens up, like, more ways to interact with Pydantic, which is cool.

00:03:34.060 --> 00:03:34.500
Yeah.

00:03:34.500 --> 00:03:34.540
Yeah.

00:03:34.540 --> 00:03:37.840
So, they've got a lot of stuff working already.

00:03:37.840 --> 00:03:43.940
They want people to be able to experiment and try out their base model changes.

00:03:43.940 --> 00:03:50.260
A lot of the same features for validation, but there's new method names, and it is a change.

00:03:50.260 --> 00:03:54.200
Data classes, serialization, strict mode, different schemas.

00:03:54.200 --> 00:03:56.380
Lots of changes for V2.

00:03:56.660 --> 00:03:58.600
So, I'd like people to try it out.

00:03:58.600 --> 00:04:04.840
There is a lot of stuff still under construction, mostly documentation.

00:04:05.840 --> 00:04:12.240
And some of the base settings have changed from there were base settings, and now they're going to be in Pydantic settings.

00:04:12.240 --> 00:04:13.280
That's not quite ready.

00:04:13.280 --> 00:04:18.240
So, there's still some work to do, even in the migration guide.

00:04:18.240 --> 00:04:21.460
So, they've gotten a start on the migration guide, but it's not there.

00:04:21.460 --> 00:04:27.020
As you see on, like, some of the links, there's changes to data classes, changes to base model.

00:04:27.020 --> 00:04:31.300
Some of the stuff's already there, but it's still under construction.

00:04:31.300 --> 00:04:32.500
So, pretty exciting.

00:04:33.160 --> 00:04:39.160
I'm definitely excited, and the 5 to 50 times faster, that's no joke.

00:04:39.160 --> 00:04:41.340
There's, you might think, okay, well, what are you doing?

00:04:41.340 --> 00:04:44.880
I'm, like, parsing, like, a settings file, or I got a single JSON document, whatever.

00:04:44.880 --> 00:04:54.600
All of FastAPI is deeply, not all, but much of FastAPI is deeply based on exchanging rich data with Pydantic, right?

00:04:54.600 --> 00:04:58.480
So, your API layer could get much faster, right?

00:04:58.480 --> 00:05:01.460
And you can also use this, people maybe don't realize it.

00:05:02.080 --> 00:05:04.720
You can use this with other frameworks as well.

00:05:04.720 --> 00:05:05.860
You could use it with Flask.

00:05:05.860 --> 00:05:07.180
You could use it with Pyramid.

00:05:07.180 --> 00:05:14.120
You know, FastAPI is cool, because you can put just, there's a argument of type Pydantic model, and it automatically fills it all in.

00:05:14.120 --> 00:05:18.640
But all you've got to do is just take, here's the post dictionary, and feed it to a Pydantic model.

00:05:18.640 --> 00:05:21.920
Like, just inside the function is the first line, and you're in the same place.

00:05:22.320 --> 00:05:24.320
So, you can use this across all these areas.

00:05:24.320 --> 00:05:31.960
Then, for example, Pythonbytes.fm is powered by Beanie, which is Pydantic plus MongoDB plus Async, which is awesome.

00:05:31.960 --> 00:05:36.160
But every single database record comes back, goes through Pydantic.

00:05:36.160 --> 00:05:48.060
And if you're using something like Beanie or SQL model, in FastAPI, your data layer goes through Pydantic, and your web layer goes through, there's like multi-layered Pydantic operations on every interaction.

00:05:48.060 --> 00:05:53.640
And so, making that part five to 50 times faster is just huge, right?

00:05:53.640 --> 00:05:56.000
That's a really big surface area to make a lot faster.

00:05:56.000 --> 00:06:00.920
I got speedups as well to talk about later in the show, but it's not that much area.

00:06:00.920 --> 00:06:01.440
That's awesome.

00:06:01.440 --> 00:06:10.200
One of the things you bring up, which is interesting, is that a lot of people, I mean, there's tons of people that use Pydantic just by itself with their own code.

00:06:10.200 --> 00:06:20.840
But the people that mostly touch it through FastAPI or Beanie or something, they may have to wait until those projects bring on the changes then,

00:06:21.180 --> 00:06:24.860
unless those projects have branches for B2, which who knows?

00:06:24.860 --> 00:06:26.760
I, yeah, yeah, I hope so.

00:06:26.760 --> 00:06:35.980
And maybe there's a way, you know, I think the breaking changes in, say, base model, for example, are, I think they're kind of deprecated already.

00:06:35.980 --> 00:06:40.200
And 1.10.7, just they're still there, right?

00:06:40.200 --> 00:06:42.460
But I think they become breaking changes here.

00:06:42.460 --> 00:06:49.780
If you're also, if you're doing model validation, a lot of the function names gets changed.

00:06:50.520 --> 00:06:53.180
Yeah, like things like from RRM go away.

00:06:53.180 --> 00:06:59.620
There's a bunch of little, I don't think they're big changes that are going to be a huge problem for people, but they are incompatibilities, as you point out.

00:06:59.620 --> 00:07:06.380
Both Roman Wright and Sebastian Ramirez seem to be really on top of their projects, respectively, Beanie and FastAPI.

00:07:06.380 --> 00:07:10.900
So I feel like by the time this becomes fully released, they'll be there.

00:07:11.280 --> 00:07:14.920
Yeah. And what's one of the reasons why I covered is to try to like promote everybody.

00:07:14.920 --> 00:07:15.860
Nudge, nudge. Hey, exactly.

00:07:15.860 --> 00:07:16.520
Nudge, nudge.

00:07:16.520 --> 00:07:18.040
Exactly.

00:07:18.040 --> 00:07:18.620
Please.

00:07:19.920 --> 00:07:21.160
So, yes, indeed.

00:07:21.160 --> 00:07:30.340
Yeah, it would be awesome that when this comes out for just, boom, V2 is out, like you just update all the packages that depend upon it and you can adopt it right away.

00:07:30.340 --> 00:07:30.800
That would be great.

00:07:30.840 --> 00:07:39.080
But to be fair, like let's say I'm working on a side project that's using FastAPI or Beanie or something and I don't have it in production yet.

00:07:39.080 --> 00:07:42.380
I'd be like, yeah, let's use V2 right away.

00:07:42.800 --> 00:07:46.040
But if I've got a production system, I don't want to switch right away.

00:07:46.040 --> 00:07:54.360
So I get that there's projects at different levels and group projects like FastAPI and Beanie have to keep that in mind.

00:07:54.360 --> 00:07:55.060
So, yeah.

00:07:55.060 --> 00:07:56.160
All right.

00:07:56.160 --> 00:07:56.820
All right.

00:07:56.820 --> 00:07:58.180
Well, this is exciting to me.

00:07:58.180 --> 00:08:00.360
I know this has been coming for a long time.

00:08:00.360 --> 00:08:01.440
So excellent work.

00:08:01.440 --> 00:08:02.440
What you got for us?

00:08:02.440 --> 00:08:05.780
Well, that's a quick real time follow up.

00:08:05.780 --> 00:08:07.840
I interviewed Samuel Colvin.

00:08:07.840 --> 00:08:12.380
He loves to do stuff on the fourth of months, apparently, on August 4th as well.

00:08:12.380 --> 00:08:15.300
Last year called PyTanic V2, The Plan.

00:08:15.300 --> 00:08:17.660
So people can check that out if they're interested.

00:08:17.660 --> 00:08:20.620
But let's talk about something really small, okay?

00:08:20.620 --> 00:08:21.360
Okay.

00:08:21.360 --> 00:08:23.580
From a friend of the show, Miguel Grinberg.

00:08:23.580 --> 00:08:26.480
And he created this thing called MicroDot.

00:08:26.480 --> 00:08:28.320
MicroDot, it's very small.

00:08:28.320 --> 00:08:33.040
It's bigger even than like the semi-dot or the regular dot.

00:08:33.040 --> 00:08:33.780
Very small.

00:08:33.780 --> 00:08:36.980
No, so what this is.

00:08:36.980 --> 00:08:37.720
Yeah.

00:08:37.720 --> 00:08:38.860
So back to web frameworks.

00:08:39.700 --> 00:08:43.820
This is the impossibly small web framework for Python and MicroPython.

00:08:43.820 --> 00:08:51.800
So it's, I believe it's reason for existence really is to basically bring something like Flask

00:08:51.800 --> 00:08:54.380
to MicroPython and CircuitPython, which is cool.

00:08:54.380 --> 00:09:00.360
However, it also runs under standard CPython, which opens up some interesting possibilities as well.

00:09:00.360 --> 00:09:00.740
Cool.

00:09:00.740 --> 00:09:03.660
So if we go down here.

00:09:03.660 --> 00:09:10.340
So if you're familiar with the Flask API, you should be real familiar with MicroDot.

00:09:10.340 --> 00:09:13.180
So app equals, instead of Flask, you say MicroDot.

00:09:13.180 --> 00:09:13.920
Got a function.

00:09:13.920 --> 00:09:17.120
It says, I want to do an app.route on it.

00:09:17.120 --> 00:09:24.080
Or I don't know if he supports direct verb, HTTP verbs there, like app.get, app.post, like Flask

00:09:24.080 --> 00:09:26.440
adopted recently, but app.route for sure.

00:09:26.440 --> 00:09:31.900
And then one of the differences is you have to pass a request object into the functions

00:09:31.900 --> 00:09:32.260
there.

00:09:32.260 --> 00:09:37.120
Whereas Flask has this thread local ambient variation of this thing.

00:09:37.460 --> 00:09:43.380
So you'll get like a 500 error if you try to, you know, just run this directly without adding

00:09:43.380 --> 00:09:43.780
that request.

00:09:43.780 --> 00:09:44.720
So it's easy to overlook.

00:09:44.720 --> 00:09:50.620
But other than that, other than the fact that there's a request parameter to the views, basically

00:09:50.620 --> 00:09:51.260
the same thing.

00:09:51.260 --> 00:09:52.020
Okay.

00:09:52.020 --> 00:09:53.920
So yeah, that's pretty interesting.

00:09:53.920 --> 00:10:00.040
Now, there's a bunch of compromises that are made here because MicroPython doesn't support

00:10:00.040 --> 00:10:00.420
Jinja.

00:10:00.420 --> 00:10:03.100
It doesn't support Flask, all of these different things.

00:10:03.100 --> 00:10:03.640
All right.

00:10:03.720 --> 00:10:09.260
So there is a template language, but it's not Jinja, right?

00:10:09.260 --> 00:10:13.360
So there's a bit of a migration if you were going to take this on, right?

00:10:13.360 --> 00:10:18.040
So you can run it under CPython, but you can also run it under MicroPython.

00:10:18.040 --> 00:10:20.140
There's the HTTP methods.

00:10:20.140 --> 00:10:21.820
I think you see the old style.

00:10:21.820 --> 00:10:24.520
No, no, there's an app.get.

00:10:24.520 --> 00:10:28.300
You can do the old style where you pass the method names like get and post, or you can just

00:10:28.300 --> 00:10:29.060
do an app.get.

00:10:29.740 --> 00:10:34.800
But yeah, again, if you're familiar with Flask, the way you do routes, the way you pass data

00:10:34.800 --> 00:10:39.160
into the functions, all those things are absolutely the same, which is pretty cool.

00:10:39.160 --> 00:10:45.220
One thing you can do is you can return JSON responses, and you can even just return a dictionary,

00:10:45.220 --> 00:10:46.960
which I don't think you can do in Flask.

00:10:46.960 --> 00:10:50.080
Maybe you can, but I think you have to JSONify it.

00:10:50.080 --> 00:10:51.720
I think you have to say Flask.jsonify.

00:10:51.720 --> 00:10:53.540
So this is kind of an upgrade, I would say.

00:10:53.540 --> 00:10:53.580
Okay.

00:10:53.580 --> 00:10:59.680
So if you have a little tiny thing, like a little tiny thing like this, Brian.

00:10:59.680 --> 00:11:00.420
Okay.

00:11:00.420 --> 00:11:01.060
All right, here.

00:11:01.060 --> 00:11:05.960
However big is that, you know, like not about the size of my hand, like the half the way

00:11:05.960 --> 00:11:06.860
across the pole of my hand.

00:11:06.860 --> 00:11:09.700
I got one of these little tiny MicroPython, CircuitPython things.

00:11:09.700 --> 00:11:15.880
You can now put APIs on here, and you can put even really interesting things like it has support

00:11:15.880 --> 00:11:17.640
for concurrency.

00:11:18.060 --> 00:11:22.260
So Flask doesn't support directly having async and await, I don't believe.

00:11:22.260 --> 00:11:23.340
Not fully, anyway.

00:11:23.340 --> 00:11:24.820
You got to switch over to Quart to do that.

00:11:24.820 --> 00:11:28.000
I think they partially support it, but not full async and await.

00:11:28.000 --> 00:11:35.360
But you can use the MicroPython asyncio extension here and get APIs running with full async and

00:11:35.360 --> 00:11:39.140
await concurrency support doing JSON or other things.

00:11:39.140 --> 00:11:40.080
Maybe with Pydantic.

00:11:40.080 --> 00:11:40.720
Not sure.

00:11:40.720 --> 00:11:41.640
That's pretty cool.

00:11:41.640 --> 00:11:46.020
Because a lot of the, I mean, that's just an easy, like throwing a REST API or some

00:11:46.020 --> 00:11:52.040
sort of API on something to throw back JSON to, that would be really cool.

00:11:52.040 --> 00:11:55.660
And you don't need, I mean, for applications like that, you don't need a lot of templating

00:11:55.660 --> 00:11:56.200
around.

00:11:56.200 --> 00:11:57.140
Yeah.

00:11:57.140 --> 00:12:00.540
And so let's see, go to the core extensions here.

00:12:00.540 --> 00:12:02.840
You can see there's actually a bunch of cool core extensions.

00:12:02.840 --> 00:12:04.620
So got the async and await support.

00:12:04.620 --> 00:12:10.700
So all you got to do is just, where I'm going to scroll, just write async def endpoint,

00:12:10.700 --> 00:12:11.080
right?

00:12:11.080 --> 00:12:11.520
Boom.

00:12:11.520 --> 00:12:12.200
Off it goes.

00:12:12.200 --> 00:12:12.740
Yeah.

00:12:12.740 --> 00:12:14.960
Because you really want to async that hello world.

00:12:14.960 --> 00:12:15.520
Yeah.

00:12:15.520 --> 00:12:16.620
For hello world, not so much.

00:12:16.620 --> 00:12:19.320
But if you're talking to, you know, files that's similar database or something.

00:12:19.320 --> 00:12:19.880
Yeah.

00:12:19.880 --> 00:12:22.080
You can use, what is that?

00:12:22.080 --> 00:12:23.080
MicroTemplate.

00:12:23.080 --> 00:12:25.400
It says U-Template, but I bet it's a micro.

00:12:25.400 --> 00:12:27.940
I think it's pronounced template.

00:12:27.940 --> 00:12:29.540
Template.

00:12:29.540 --> 00:12:29.720
Yeah.

00:12:29.720 --> 00:12:30.520
U-Template.

00:12:30.520 --> 00:12:38.820
It's a lightweight and memory efficient template for Python, which it looks very, very

00:12:38.820 --> 00:12:40.160
Jinja-like as well.

00:12:40.160 --> 00:12:43.200
So that's a pretty straightforward thing, but it's not identical, right?

00:12:43.200 --> 00:12:44.300
What else we got?

00:12:44.300 --> 00:12:45.920
Ooh, this is Jinja, isn't it?

00:12:45.920 --> 00:12:47.600
Oh, can you?

00:12:47.600 --> 00:12:49.480
Oh, you.

00:12:49.480 --> 00:12:51.100
But no, hold on.

00:12:51.100 --> 00:12:52.160
It's CPython only.

00:12:52.160 --> 00:12:53.060
Oh, okay.

00:12:53.060 --> 00:12:53.560
Okay.

00:12:53.560 --> 00:12:54.040
Got it.

00:12:54.040 --> 00:12:56.280
So, because it's not supported in MicroPython.

00:12:56.280 --> 00:12:57.260
Got it.

00:12:57.260 --> 00:13:01.340
But if you're doing it on CPython, you can add those templates.

00:13:01.340 --> 00:13:01.940
Yes.

00:13:01.940 --> 00:13:03.460
This is actually why it's pretty interesting to me.

00:13:03.460 --> 00:13:07.980
So you can do TLS, HTTPS support, right?

00:13:07.980 --> 00:13:08.780
Which is pretty cool.

00:13:08.780 --> 00:13:10.220
You have web sockets.

00:13:10.220 --> 00:13:11.660
You have asynchronous web sockets.

00:13:11.660 --> 00:13:15.700
You have cores, cross-origin, resource sharing settings.

00:13:15.700 --> 00:13:17.940
And you can even deploy it.

00:13:17.940 --> 00:13:23.460
So it comes with its own little web server, which you can run on your MicroPython daily,

00:13:23.460 --> 00:13:24.160
right?

00:13:24.160 --> 00:13:29.060
But if you were going to put this into a big data center on a huge rack of servers,

00:13:29.060 --> 00:13:30.820
that might not be the best choice.

00:13:30.820 --> 00:13:33.900
So you can run it on uWSGI, which is awesome.

00:13:33.900 --> 00:13:35.100
You can run it on GUnicorn.

00:13:35.100 --> 00:13:45.260
You can even run it on GUnicorn with UVicorn workers to get the awesome LibUV high-performance

00:13:45.260 --> 00:13:46.580
async support, right?

00:13:46.580 --> 00:13:52.600
So you can deploy it onto kind of the top-tier Python stuff, put Nginx in front of it and all

00:13:52.600 --> 00:13:52.800
that.

00:13:52.800 --> 00:13:53.680
It's pretty cool, right?

00:13:53.680 --> 00:13:54.220
Yeah.

00:13:54.220 --> 00:14:00.680
Now, one of the ways you run web apps on servers, especially in Python, because the threading

00:14:00.680 --> 00:14:06.580
support is not as friction-free, I guess, you know, like the GIL and all that, is you'll

00:14:06.580 --> 00:14:08.580
farm it out into multiple workers, right?

00:14:08.580 --> 00:14:11.580
So I can't remember what we have for Python by it.

00:14:11.580 --> 00:14:12.540
It's not too many.

00:14:12.640 --> 00:14:14.520
So I can't remember what we have for Python.

00:14:14.520 --> 00:14:16.520
So I can't remember what we have for Python.

00:14:16.520 --> 00:14:18.520
So I can't remember what we have for Python.

00:14:18.520 --> 00:14:20.520
So I can't remember what we have for Python.

00:14:20.520 --> 00:14:22.520
So I can't remember what we have for Python.

00:14:22.520 --> 00:14:25.680
It'll automatically send the request over to another one, right?

00:14:25.680 --> 00:14:30.460
Now, usually there's maybe a couple of limits, but one of the limits you really want to consider

00:14:30.460 --> 00:14:32.640
is I don't want to run the machine out of memory.

00:14:32.640 --> 00:14:36.340
So I think the ones we use like 150 megs per worker process.

00:14:36.340 --> 00:14:41.100
So at some point, they only create so many, and then the server's like, okay, I've had it.

00:14:41.100 --> 00:14:45.400
But with this little thing that runs on MicroPython, you could scale the heck out of it.

00:14:45.400 --> 00:14:48.180
You could have a ton of worker processes under MicroWSGI.

00:14:48.180 --> 00:14:49.300
Oh, yeah.

00:14:49.300 --> 00:14:52.240
Or under UVicorn, right?

00:14:52.240 --> 00:14:56.240
And I actually did a little super simple test.

00:14:56.240 --> 00:15:01.500
I wrote the Flask equivalent of Hello World, literally exactly the same code with the changes

00:15:01.500 --> 00:15:02.060
I talked about.

00:15:02.400 --> 00:15:09.580
And then the MicroPython version, sorry, the micro.version, and that one, both running on

00:15:09.580 --> 00:15:14.940
CPython, nine megs for this framework, 25 megs for the Flask framework.

00:15:14.940 --> 00:15:22.320
So maybe you can have twice as much processing horizontal scale with this thing, but deployed

00:15:22.320 --> 00:15:22.980
to real servers.

00:15:22.980 --> 00:15:28.120
So there might actually be some interesting advantages to having this really tight framework.

00:15:28.120 --> 00:15:32.280
Like I want to run it in a bunch of Docker containers that are using the smallest amount of

00:15:32.280 --> 00:15:32.500
memory.

00:15:32.500 --> 00:15:37.040
I want to farm it out and say, no, I'll have 30 worker processes on the server, not five.

00:15:37.040 --> 00:15:37.620
I don't know.

00:15:37.620 --> 00:15:37.960
We'll see.

00:15:37.960 --> 00:15:38.420
Yeah.

00:15:38.420 --> 00:15:39.020
Yeah.

00:15:39.020 --> 00:15:43.220
So Panful is pretty psyched about the memory saving out there as well.

00:15:43.220 --> 00:15:44.860
So I think it's good.

00:15:44.860 --> 00:15:45.400
Yeah.

00:15:45.400 --> 00:15:49.560
And I mean, for lots of jobs where you don't need, if you don't need the power, don't use

00:15:49.560 --> 00:15:49.900
the power.

00:15:49.900 --> 00:15:50.260
So.

00:15:50.260 --> 00:15:50.700
Yeah.

00:15:50.700 --> 00:15:51.460
Yeah.

00:15:51.460 --> 00:15:51.880
Pretty neat.

00:15:51.880 --> 00:15:53.380
So well done, Miguel.

00:15:53.380 --> 00:15:54.520
And yeah.

00:15:54.520 --> 00:15:58.780
Now, Brian, let me take just a moment and tell everyone about our sponsor.

00:15:59.200 --> 00:16:04.140
This episode of Python Bytes is brought to you by Influx Data, the makers of InfluxDB.

00:16:04.140 --> 00:16:11.080
InfluxDB is a database purpose built for handling time series data at a massive scale for real

00:16:11.080 --> 00:16:11.720
time analytics.

00:16:11.720 --> 00:16:17.600
Developers can ingest, store, and analyze all types of time series data, metrics, events,

00:16:17.600 --> 00:16:19.360
traces in a single platform.

00:16:20.040 --> 00:16:22.180
So dear listener, let me ask you a question.

00:16:22.180 --> 00:16:27.100
How would boundless cardinality and lightning fast SQL queries impact the way you develop

00:16:27.100 --> 00:16:28.260
real time applications?

00:16:28.260 --> 00:16:34.580
InfluxDB processes large time series data sets and provides low latency SQL queries, making

00:16:34.580 --> 00:16:39.700
it a go-to choice for developers building real time applications and seeking crucial insights.

00:16:39.700 --> 00:16:46.120
Optimized for developer efficiency, InfluxDB helps you create IoT, analytics, and cloud applications

00:16:46.120 --> 00:16:49.180
using timestamped data rapidly and at scale.

00:16:49.180 --> 00:16:54.920
It's designed to ingest billions of data points in real time with boundless cardinality.

00:16:54.920 --> 00:17:01.320
InfluxDB streamlines building once and deploying across various products and environments from the

00:17:01.320 --> 00:17:03.280
edge, on-premise, and to the cloud.

00:17:03.280 --> 00:17:08.020
Try it for free at pythonbytes.fm/influxDB.

00:17:08.020 --> 00:17:10.100
The links in your podcast show notes.

00:17:10.100 --> 00:17:12.300
Thanks to Influx Data for supporting the show.

00:17:12.300 --> 00:17:14.220
Over to you.

00:17:14.220 --> 00:17:14.780
What's your next one?

00:17:15.580 --> 00:17:17.540
I want to talk about GitHub Actions a bit.

00:17:17.540 --> 00:17:20.900
So a lot of my workflows have moved over to GitHub Actions.

00:17:20.900 --> 00:17:26.420
And so there's actually three projects that I wanted to talk about that I thought were neat.

00:17:26.420 --> 00:17:29.700
And they're all kind of in the GitHub Action genre.

00:17:29.700 --> 00:17:30.460
Whatcha got?

00:17:30.460 --> 00:17:31.220
Whatcha got?

00:17:31.220 --> 00:17:32.620
Whatcha got first?

00:17:32.620 --> 00:17:35.240
Whatcha?

00:17:35.240 --> 00:17:37.180
Watch GHA.

00:17:37.180 --> 00:17:39.240
It comes from Ned Batchelder.

00:17:40.000 --> 00:17:47.120
This is a, a, a, just a simple tool to, to watch your GitHub Action progress from a command line.

00:17:47.820 --> 00:17:50.540
So, pretty, I think it's a command line thing.

00:17:50.540 --> 00:17:51.400
Looks like command line.

00:17:51.400 --> 00:17:58.080
and so it looks, so you can, it has like a little progress bar thing, progress dots that go green.

00:17:58.080 --> 00:18:01.480
And then they start out gray and then they go white and green and stuff.

00:18:01.660 --> 00:18:06.760
to see the different things you got like, you're running three, seven on Ubuntu.

00:18:06.760 --> 00:18:08.180
By Pia.

00:18:08.180 --> 00:18:13.920
So if you've got a big matrix, that's doing a lot of stuff, it's kind of hard to keep up with what, what all's going on.

00:18:14.000 --> 00:18:18.240
So, this is kind of neat to watch just a little tool from Ned.

00:18:18.240 --> 00:18:18.820
Thanks, Ned.

00:18:18.820 --> 00:18:33.260
one of the other things I was thinking about, so I just, my talk at PyCascades was talking about, that you can share, you can just, you can share packages without actually ever building it.

00:18:33.260 --> 00:18:40.540
because pip install will build your wheel for you if, if it's not built already, but you probably, you probably should test that.

00:18:40.540 --> 00:18:48.680
and one of the ways you can test some of that building is with, with Enix, build and inspect Python package.

00:18:48.680 --> 00:18:57.620
so this is a GitHub action that, will, it does a lot of stuff, but it does, it does a build to make sure the build works.

00:18:57.620 --> 00:19:02.400
it also does, has a linter to, to lint the wheel contents.

00:19:02.400 --> 00:19:07.920
it also uploads the, wheel and the source distribution as GitHub action artifacts.

00:19:08.080 --> 00:19:13.680
So it actually does generate the wheel for you, as an artifact, which is kind of neat.

00:19:13.680 --> 00:19:24.680
the, it also, one of the things that's, what's one of the things that's always a mystery to me is like the makes, making sure I have everything that I want in the S dist, the source distribution.

00:19:24.680 --> 00:19:27.720
And, this, this will, lint that.

00:19:27.720 --> 00:19:32.500
And also, well, I guess it doesn't lint the contents of the S dist, but it does print them out.

00:19:32.500 --> 00:19:39.080
So, print does a tree of the S dist and the wheel in the output so that you, you don't have to download it to check it.

00:19:39.080 --> 00:19:41.880
You can just look at it in your GitHub output.

00:19:41.880 --> 00:19:45.240
Make sure all the files and resources you might need to send out come along.

00:19:45.240 --> 00:19:45.720
Yeah.

00:19:45.860 --> 00:19:48.180
and this, yeah.

00:19:48.180 --> 00:19:57.040
I, I had recently made a change to a package and it took out the tests and I had somebody say, Oh, look, we, we want the tests back in.

00:19:57.040 --> 00:19:58.100
So it's kind of nice.

00:19:58.420 --> 00:20:03.340
so, let's, I guess that's, that's it with that.

00:20:03.340 --> 00:20:08.700
It's kind of a neat, GitHub action thing, that you just put it, put it in.

00:20:08.700 --> 00:20:09.740
It's one of those actions.

00:20:09.740 --> 00:20:11.940
So you just like specify it and it just works.

00:20:11.940 --> 00:20:12.400
It's nice.

00:20:12.400 --> 00:20:20.180
the, the third thing I wanted to bring up was, py test, GitHub actions, annotate failures.

00:20:20.760 --> 00:20:26.320
so this is a, one of the, just a nice extra thing that I hadn't heard about before.

00:20:26.320 --> 00:20:33.660
py test it's under the py test dev, umbrella, but it, it is a, it's a pip install sort of thing.

00:20:33.660 --> 00:20:42.660
And what it does is it makes sure that the, the, all the proper stuff gets output, so that you can have nice annotated failure.

00:20:42.660 --> 00:20:46.840
Your asserts, if there's failures, it's annotated nicely and github actions.

00:20:46.840 --> 00:20:47.440
That's it.

00:20:47.440 --> 00:20:49.620
Just some fun GitHub action stuff.

00:20:49.620 --> 00:20:50.100
Yeah.

00:20:50.340 --> 00:20:54.140
Once you really start getting into CI, CD, it's, it's fun.

00:20:54.140 --> 00:20:56.460
And you're just like, oh, and now that it's automated, we could do this.

00:20:56.460 --> 00:20:57.260
So we could do that.

00:20:57.260 --> 00:20:58.260
Yeah.

00:20:58.260 --> 00:21:04.720
And then, but when they automate all the things and then when things go wrong, you're like, oh God, then we have to pull it down and check it again.

00:21:04.720 --> 00:21:10.060
But having, so having some of these debug stuff and things up, up in the cloud, it's good.

00:21:10.060 --> 00:21:10.320
Yeah.

00:21:10.320 --> 00:21:10.900
Very handy.

00:21:10.900 --> 00:21:12.200
Excellent.

00:21:12.200 --> 00:21:12.800
All right.

00:21:12.800 --> 00:21:15.740
Well, I have a PEP for us to discuss.

00:21:15.740 --> 00:21:16.380
Okay.

00:21:16.380 --> 00:21:19.660
709 inlined comprehensions.

00:21:19.920 --> 00:21:24.840
Now, this is a debate that I seem to have only on YouTube.

00:21:24.840 --> 00:21:31.520
if I'll do, like, I've done some videos about list comprehensions or other sort of design patterns.

00:21:31.520 --> 00:21:38.740
You might involve comprehensions and people are like, oh, Michael, you said that a for loop is different than a list comprehension.

00:21:38.740 --> 00:21:41.200
But look, it says for thing in collection.

00:21:41.200 --> 00:21:42.360
And so they're the same.

00:21:42.360 --> 00:21:43.940
And so I just don't know.

00:21:43.940 --> 00:21:45.200
You just don't know what you're talking about.

00:21:45.200 --> 00:21:46.000
Like, you know what?

00:21:46.000 --> 00:21:47.000
Let's disassemble it.

00:21:47.000 --> 00:21:48.400
Let's see what it does.

00:21:48.400 --> 00:21:49.800
Is it the same disassembly?

00:21:49.800 --> 00:21:51.940
No, it's completely different disassembly.

00:21:52.080 --> 00:21:54.880
That means the implementation of list comprehensions are different.

00:21:54.880 --> 00:21:56.900
I don't care if the word for appears in both of them.

00:21:56.900 --> 00:21:58.020
They're not the same thing.

00:21:58.380 --> 00:22:04.020
This PEP brings them, kind of tries to take the both, the best of both worlds, though.

00:22:04.020 --> 00:22:14.300
And it says there are some things we do to make comprehensions work, but look like they're just right there in the same function or in line, even if you don't have a function.

00:22:14.300 --> 00:22:23.600
But in fact, there's kind of this thing behind the scenes that's happening where we create a nested function that you never see, but the interpreter creates and then calls it.

00:22:23.600 --> 00:22:25.180
And that's the interpreter.

00:22:25.180 --> 00:22:25.700
OK.

00:22:25.700 --> 00:22:27.680
The comprehension, rather.

00:22:27.680 --> 00:22:39.560
So this PEP by Carl Meyer is basically saying we could get really good performance increases if we just change that implementation a little.

00:22:39.900 --> 00:22:55.500
And the reason it's created as a nested function and not just some inline code is what if you have a variable X in your regular function and then you have X as a loop variable or as the item variable in your comprehension or things like that, right?

00:22:55.500 --> 00:22:56.800
You want them to still be isolated.

00:22:56.800 --> 00:22:59.640
So that's basically the idea here.

00:22:59.640 --> 00:23:08.260
It says comprehensions are currently compiled as nested functions, which provides isolation of the comprehension's iteration variable, but is inefficient at runtime.

00:23:08.860 --> 00:23:24.540
So PEP 709 proposes to inline list dictionary and set comprehensions into the code where they are defined and provide the expected isolation by looking at all the variables, creating a copy of them, running this in place.

00:23:24.540 --> 00:23:29.300
And then if there was a variable for that loop variable, just put the old value back, right?

00:23:29.300 --> 00:23:30.780
Kind of push and pop them there.

00:23:30.780 --> 00:23:37.220
And the benefits here are up to two times as fast as comprehensions are today.

00:23:37.800 --> 00:23:48.480
So then they said, this is translating to an 11% speed up in one sample benchmark derived from real world code that makes heavy use of comprehensions in the context of doing actual work.

00:23:48.480 --> 00:23:49.460
That's pretty cool, right?

00:23:49.460 --> 00:23:49.940
Yeah.

00:23:49.940 --> 00:23:56.640
I believe comprehensions were in general slightly faster than four loops that would just do something and put it in a list.

00:23:56.640 --> 00:23:59.640
So making it two times faster still is even better.

00:23:59.800 --> 00:24:02.480
So if this gets adopted, it's in draft form right now.

00:24:02.480 --> 00:24:11.560
I can go back to my YouTube comments and have even further nuanced discussions about like, here's yet again, how they are not the same thing, but they look similar.

00:24:11.560 --> 00:24:13.900
So yeah.

00:24:14.100 --> 00:24:20.180
I never would have thought that I should reuse a variable in a comprehension though.

00:24:20.180 --> 00:24:22.520
I don't do that, but I guess.

00:24:22.520 --> 00:24:31.560
No, I think it's like if, let's say you've got two list comprehensions, you know, X squared for X in first set.

00:24:31.560 --> 00:24:36.040
Then X, two X plus one for X in other set.

00:24:36.040 --> 00:24:37.860
Those are two separate list comprehensions.

00:24:38.020 --> 00:24:41.100
You don't want like one of those variables too.

00:24:41.100 --> 00:24:41.860
You want to keep them.

00:24:41.860 --> 00:24:45.120
They want to be like, okay, this X is only for this comprehension.

00:24:45.120 --> 00:24:46.480
That's what it's like.

00:24:46.480 --> 00:24:50.000
So if you have an embedded comprehension, you might use X in both places.

00:24:50.000 --> 00:24:50.560
Right.

00:24:50.560 --> 00:24:55.300
Or if you have an X, X and Y equals something, and then you generate a comprehension, you say X in there.

00:24:55.300 --> 00:24:56.920
Like there's a couple of, there's some weird.

00:24:56.920 --> 00:24:57.080
Yeah.

00:24:57.080 --> 00:24:57.620
Yeah.

00:24:57.620 --> 00:25:00.320
I mean, I guess I was just thinking my own style.

00:25:00.320 --> 00:25:02.460
The second one I would never do.

00:25:02.460 --> 00:25:06.000
If I had, if I was already using X, I probably wouldn't use X in the comprehension.

00:25:06.500 --> 00:25:13.340
But I'll often use I or X in a comprehension in embedded ones and don't even think about it.

00:25:13.340 --> 00:25:14.060
So yeah.

00:25:14.060 --> 00:25:14.600
Interesting.

00:25:14.600 --> 00:25:15.300
Cool.

00:25:15.300 --> 00:25:15.680
Yeah.

00:25:15.680 --> 00:25:22.620
David Poole says, I'm sure there's good reasons for it, but I wonder why comprehensions don't use name mingling strategies for their var names.

00:25:22.620 --> 00:25:25.340
Everyone's got to be named underscore underscore X.

00:25:25.340 --> 00:25:28.440
That is a good question.

00:25:28.440 --> 00:25:29.000
That reminds me of a joke.

00:25:29.400 --> 00:25:37.400
Well, so what it's doing now is it basically says, we're going to create a function.

00:25:37.400 --> 00:25:42.640
And so that variable is basically a local variable, that function, which has no influence on it.

00:25:42.640 --> 00:25:44.520
Were you going to actually tell us the joke?

00:25:44.520 --> 00:25:47.380
No, it's going to wait.

00:25:47.380 --> 00:25:47.920
Okay.

00:25:47.920 --> 00:25:48.280
All right.

00:25:48.280 --> 00:25:50.080
Or should we do it now?

00:25:50.080 --> 00:26:01.140
Oh, just, I think it was Ned Batchelor actually that mentioned that Dunder, we often talk about __init__() instead of double underscore init.

00:26:01.140 --> 00:26:05.120
But it's really underscore underscore init underscore underscore.

00:26:05.120 --> 00:26:06.680
So it's really quunder.

00:26:06.680 --> 00:26:08.120
Quunder.

00:26:08.640 --> 00:26:12.820
And so I responded to him and said, I don't think so.

00:26:12.820 --> 00:26:16.020
I think it's Dunder and Net Dunder is what it should be.

00:26:16.020 --> 00:26:18.680
But that would be Redunderant.

00:26:18.680 --> 00:26:21.480
It's pretty bad.

00:26:21.480 --> 00:26:23.880
That's pretty much on par with the joke we got at the end.

00:26:23.880 --> 00:26:25.020
So I'm preparing for people.

00:26:25.020 --> 00:26:25.960
All right.

00:26:25.960 --> 00:26:30.740
So basically the way to understand this, you can't look at the code and tell, right?

00:26:30.740 --> 00:26:34.580
Which is why people incorrectly try to correct me on YouTube.

00:26:34.960 --> 00:26:40.160
So you look at the code and it looks like, oh, it's just a for list and we took out the line breaks and put brackets.

00:26:40.160 --> 00:26:41.020
So it's the same thing.

00:26:41.020 --> 00:26:52.680
So if you look at it now, you can see if you create a function that creates a list comprehension, you'll see it creates what's called a code object of type list comprehension.

00:26:52.680 --> 00:26:54.440
Then it calls make function.

00:26:54.440 --> 00:26:58.400
Then it loads the list and then it does a bunch of stuff on it.

00:26:58.400 --> 00:27:04.720
And then it actually, you can see there's like this sub function that gets disassembled and it says, we're going to build a list, load fast, iterate it.

00:27:04.720 --> 00:27:05.720
So let's look at list append.

00:27:05.720 --> 00:27:08.920
And what's really interesting, this is the part that differs from for loops.

00:27:08.920 --> 00:27:12.320
There's a byte code called list underscore append.

00:27:12.320 --> 00:27:19.800
If you do this with a for loop where you have a list and you call append, it loads the function append and then calls append on the operands.

00:27:19.800 --> 00:27:22.860
But it's not in the runtime in a for loop.

00:27:22.860 --> 00:27:26.760
In a comprehension, there's a special byte code that runs and that's like the primary difference.

00:27:26.760 --> 00:27:34.420
So the benefit is list append is a byte code operation, not a function call.

00:27:34.420 --> 00:27:40.920
But the drawback is there's this object created, there's a stack frame created, there's a function call over to this comprehension call.

00:27:40.920 --> 00:27:43.320
There's an issue with all that stuff.

00:27:43.620 --> 00:27:52.280
So the new one just says, what we're going to do is we're going to create a new op code called load fast and clear, which is like, I'm going to load the variable X.

00:27:52.280 --> 00:28:00.120
And if there was one of those before, we're going to hang on to that just in case, you know, so we can put it back to avoid that.

00:28:00.120 --> 00:28:01.720
And then it calls build list.

00:28:01.720 --> 00:28:05.600
And like you can notice, there's no, there's no function call.

00:28:05.600 --> 00:28:07.840
So no stack frame, no extra function call.

00:28:07.840 --> 00:28:10.900
There's no list comprehension object, all those things.

00:28:10.900 --> 00:28:16.600
And so this is the new byte code operation that manages that variable isolation.

00:28:16.600 --> 00:28:19.320
And then you just do it directly, which saves you a bunch.

00:28:19.320 --> 00:28:21.060
We talked about the 2x speed there.

00:28:21.060 --> 00:28:23.440
So that's the, that's the pep.

00:28:23.440 --> 00:28:24.260
People check it out.

00:28:24.260 --> 00:28:25.040
See what you think.

00:28:25.040 --> 00:28:28.620
That's really interesting, Michael, but you had me at it's faster.

00:28:28.620 --> 00:28:29.920
I know exactly.

00:28:29.920 --> 00:28:35.060
I just want people to kind of know what's, what's happening and why it might be faster and so on.

00:28:35.060 --> 00:28:36.260
So pretty neat.

00:28:37.140 --> 00:28:45.160
You can see it does have the only possible, I guess, concern or the reason they say, why is this even a pep?

00:28:45.160 --> 00:28:46.720
Why is this not just, Hey, I made it faster.

00:28:46.720 --> 00:28:48.560
Like, why do we need to discuss this?

00:28:48.560 --> 00:28:49.080
Yeah.

00:28:49.080 --> 00:28:49.880
Like you said, right?

00:28:49.880 --> 00:28:50.500
Like it's faster.

00:28:50.500 --> 00:28:50.980
We're done.

00:28:50.980 --> 00:28:51.540
Let's go.

00:28:51.540 --> 00:28:54.940
Is there are user observable changes?

00:28:54.940 --> 00:28:58.220
If the user doesn't like themselves, basically.

00:28:58.220 --> 00:29:07.380
For example, why would a user return locals as the item you want put into a list during a list comprehension?

00:29:07.380 --> 00:29:11.480
Well, if you did do that, you would see that it's not the same as before.

00:29:11.640 --> 00:29:17.580
I have no, no idea why you would ever try to do that, but that would technically would be a breaking change.

00:29:17.580 --> 00:29:27.100
The other one was slightly more valid, perhaps is that if there's an exception inside the list comprehension, because it used to be in a separate function call.

00:29:27.100 --> 00:29:33.260
It was, there's, it would show up in the actual traceback call stack, right?

00:29:33.260 --> 00:29:35.340
But now you are not in another function.

00:29:35.340 --> 00:29:38.520
It is on a line in the OG function.

00:29:38.520 --> 00:29:41.660
So you, you don't have that.

00:29:41.660 --> 00:29:43.780
Basically it's missing from there.

00:29:43.780 --> 00:29:46.800
So you would have a slightly different traceback exception.

00:29:46.800 --> 00:29:51.680
Well, traceback, the exception would be the same, but the traceback call stack listing would be different.

00:29:51.680 --> 00:29:55.240
That potentially affects somebody, but not a lot.

00:29:55.240 --> 00:29:55.800
I don't know.

00:29:56.060 --> 00:29:57.680
It's a 2X, it's a trade-off.

00:29:57.680 --> 00:29:59.600
I would totally think it's worth taking.

00:29:59.600 --> 00:30:06.320
Yeah, but I see why that's a, it's a observable interface or an observable behavior change.

00:30:06.320 --> 00:30:07.180
So yeah.

00:30:07.180 --> 00:30:07.360
Yeah.

00:30:07.360 --> 00:30:07.820
Yeah.

00:30:07.820 --> 00:30:14.560
Although I learned from Brett Cannon just a couple of weeks ago that locals often has weird stuff in it.

00:30:14.560 --> 00:30:18.700
If you look at locals a lot, sometimes there's stuff in there that you don't recognize.

00:30:18.700 --> 00:30:19.380
Interesting.

00:30:19.380 --> 00:30:20.140
Yeah.

00:30:20.140 --> 00:30:22.100
The locals one seems like, you know what?

00:30:22.100 --> 00:30:23.020
Don't do that.

00:30:24.020 --> 00:30:27.900
But the traceback one, I can see, okay, we're always looking for this.

00:30:27.900 --> 00:30:32.360
And like, if I get an error, I try to like, look at the traceback to figure out what to tell people.

00:30:32.360 --> 00:30:33.080
Or I don't know.

00:30:33.080 --> 00:30:36.060
Theoretically could have, it still seems unlikely.

00:30:36.300 --> 00:30:41.380
I feel like you shouldn't depend upon what's listed there, but I'm sure somebody does somewhere.

00:30:41.380 --> 00:30:43.880
Well, like IDE makers and things like that.

00:30:43.880 --> 00:30:44.140
Yeah.

00:30:44.140 --> 00:30:44.560
Yeah.

00:30:44.560 --> 00:30:45.340
Cool.

00:30:45.340 --> 00:30:45.920
All right.

00:30:45.920 --> 00:30:48.140
Well, that's it for all of our items.

00:30:48.140 --> 00:30:49.500
You got any extras?

00:30:49.960 --> 00:30:50.440
I don't.

00:30:50.440 --> 00:30:51.040
I don't.

00:30:51.040 --> 00:30:51.580
Do you?

00:30:51.580 --> 00:30:58.180
I thought I didn't have any extras, but I think by the time, I'm going to try to predict the future a little bit because I have some control over it.

00:30:58.180 --> 00:30:59.180
So I do have an extra.

00:31:00.300 --> 00:31:03.220
I'm going to be releasing either today or tomorrow.

00:31:03.220 --> 00:31:06.460
And by the time this podcast comes out, this is going to be released.

00:31:06.460 --> 00:31:09.440
But if you're watching it live, it's not yet released.

00:31:09.440 --> 00:31:14.160
So I'm going to be releasing a new course, Python Web Apps That Fly with CDNs.

00:31:14.160 --> 00:31:26.400
It's just over a three-hour course that's all about taking CDNs and applying them to Flask web apps and also hosting video content and large files and how do you geo-replicate that.

00:31:26.400 --> 00:31:36.600
We use a lot of these techniques in Python Bytes to make the website faster as well as to deliver terabytes of MP3s to people.

00:31:36.600 --> 00:31:38.480
So check that out.

00:31:38.480 --> 00:31:40.320
I will put a link in the show notes.

00:31:40.320 --> 00:31:46.200
Again, if you're listening live, this is not out yet, but it will be out by the time the MP3 hits your podcast player.

00:31:46.200 --> 00:31:48.420
So if you have the audio-only version, go check it out.

00:31:48.420 --> 00:31:49.260
Link's in the show notes.

00:31:49.260 --> 00:31:49.780
Nice.

00:31:49.780 --> 00:31:51.880
Yeah, I think that's a really, really cool course.

00:31:51.880 --> 00:31:57.020
I think there's so much people can get out of it in terms of like it's really easy.

00:31:57.020 --> 00:32:01.820
You know, 30 minutes and you're like, oh, our app is so much faster and we can use smaller servers.

00:32:01.820 --> 00:32:02.660
That's really great.

00:32:02.660 --> 00:32:05.200
Well, three hours plus 30 minutes.

00:32:05.200 --> 00:32:06.120
Yes.

00:32:06.120 --> 00:32:09.800
Well, once you know the thing, it's probably 30 minutes to apply it to your app.

00:32:09.800 --> 00:32:10.260
That's what I mean.

00:32:10.260 --> 00:32:10.840
Yeah.

00:32:10.840 --> 00:32:18.220
David Poole says, the traceback one could be worked around if the debug compiled used the old function style method,

00:32:18.220 --> 00:32:21.680
like aggressive optimizations and GCC with inline functions.

00:32:22.180 --> 00:32:22.620
Okay.

00:32:22.620 --> 00:32:23.380
Possibly.

00:32:23.380 --> 00:32:23.900
Interesting.

00:32:23.900 --> 00:32:27.100
You would have to have people buy into that, but right.

00:32:27.100 --> 00:32:36.520
I mean, I'm sure, Brian, you're very well aware of the debug versus release builds and optimization levels and all that stuff in C, right?

00:32:36.520 --> 00:32:37.120
No.

00:32:37.120 --> 00:32:38.920
I mean, yes, but I don't use them.

00:32:38.920 --> 00:32:40.400
No, you don't use that.

00:32:40.400 --> 00:32:46.260
Well, I don't, I personally don't like to, I don't like to test in something my user isn't going to see.

00:32:46.260 --> 00:32:49.020
So I always test in optimized released.

00:32:49.020 --> 00:32:50.020
Got it.

00:32:50.020 --> 00:32:50.360
Yeah.

00:32:50.360 --> 00:32:50.580
Yeah.

00:32:50.580 --> 00:32:52.720
But it can make a big, it can make a big difference.

00:32:52.720 --> 00:32:56.040
But in the Python world, we don't really discuss that so much.

00:32:56.040 --> 00:32:56.420
Right.

00:32:56.420 --> 00:32:57.360
Yeah.

00:32:57.360 --> 00:33:14.600
And except for the comment, the one thing to be aware of that I would, while we're, while we're on it, we probably haven't mentioned this lately is asserts are awesome in your test code, but they're not that great in your, it actually, they're, they're pretty great in your function code also, but just don't depend on, on it.

00:33:14.600 --> 00:33:19.500
Because assert lines could be completely removed if you have the optimization on.

00:33:19.500 --> 00:33:19.880
So.

00:33:19.880 --> 00:33:20.520
Absolutely.

00:33:20.520 --> 00:33:21.180
Yeah.

00:33:21.180 --> 00:33:21.460
All right.

00:33:21.460 --> 00:33:22.220
You ready for a joke?

00:33:22.600 --> 00:33:23.040
Yes.

00:33:23.040 --> 00:33:24.220
You fan of movies?

00:33:24.220 --> 00:33:25.980
Like watching, watching movies and stuff?

00:33:25.980 --> 00:33:26.500
Yeah.

00:33:26.500 --> 00:33:27.540
I just went to a great movie.

00:33:27.540 --> 00:33:27.840
Yeah.

00:33:27.840 --> 00:33:28.060
So.

00:33:28.060 --> 00:33:28.580
Nice.

00:33:28.580 --> 00:33:34.860
Well, as a software person, especially if you do a lot with Linux or macOS, you might not be able to watch the movies too much.

00:33:34.860 --> 00:33:37.100
This one says, I can't watch movies on my computer.

00:33:37.100 --> 00:33:38.580
All it does is bash scripts.

00:33:38.580 --> 00:33:41.180
Bash on the scripts of the movie.

00:33:41.180 --> 00:33:41.600
Oh.

00:33:41.600 --> 00:33:42.640
Not plot.

00:33:42.640 --> 00:33:45.880
Or, or run shelf scripts.

00:33:45.880 --> 00:33:46.580
I'm not sure which.

00:33:46.580 --> 00:33:47.640
Okay.

00:33:47.640 --> 00:33:48.140
That's funny.

00:33:48.140 --> 00:33:48.720
I think.

00:33:48.720 --> 00:33:49.080
Sort of.

00:33:49.080 --> 00:33:49.700
Yeah.

00:33:49.700 --> 00:33:51.320
Somewhat.

00:33:52.220 --> 00:34:01.280
I have an incredible one that I want to put up, but it's like only video that has music and no, no spoken word.

00:34:01.280 --> 00:34:03.540
So I don't think it fits for this format, but I'll, you know what?

00:34:03.540 --> 00:34:04.160
I'll throw it in.

00:34:04.160 --> 00:34:04.920
I'll throw it in.

00:34:04.920 --> 00:34:06.140
People also check out the movie.

00:34:06.140 --> 00:34:07.780
It's about releasing stuff to production.

00:34:07.780 --> 00:34:09.440
So it's, it's pretty epic.

00:34:09.440 --> 00:34:10.260
I'll put it in the list.

00:34:10.260 --> 00:34:15.320
But the one we won't play is something that's like 30 seconds long that has nothing but music.

00:34:15.320 --> 00:34:17.060
Cool.

00:34:17.060 --> 00:34:17.560
Nice.

00:34:17.560 --> 00:34:18.120
All right.

00:34:18.120 --> 00:34:19.620
Is that all we got?

00:34:19.620 --> 00:34:20.580
That's all we got.

00:34:20.580 --> 00:34:21.020
It's a wrap.

00:34:21.020 --> 00:34:22.220
It's a wrap.

00:34:22.220 --> 00:34:22.560
Yeah.

00:34:22.560 --> 00:34:23.480
Thanks as always.

00:34:23.480 --> 00:34:24.080
Thank you.

00:34:24.080 --> 00:34:24.280
See you later.

