WEBVTT
00:00:00.100 -->
00:00:11.580Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds. This is episode 445, can't believe that, recorded August 18th, 2025. I am Brian
00:00:11.740 -->
00:00:17.100Aukin. And I'm Michael Kennedy. This episode is sponsored by Sentry, Python error and performance
00:00:17.340 -->
00:00:32.300monitoring. Thank you, Sentry. And if you'd like to get a hold of us, maybe give us some topic ideas that you'd like us to cover on the show, that would be awesome. Or just comment on something or just say hi, you can reach us on both BlueSky and Mastodon, and the links are in the show notes.
00:00:32.880 -->
00:00:50.860And if you'd like to join us live for the live performance, performance, pythonbytes.fm/live, or you can also use that link to find out when we're going to record next or just find out where the YouTube page is so that you can subscribe and watch them later.
00:00:51.220 -->
00:00:51.620That'd be great.
00:00:52.200 -->
00:00:57.380And finally, we'd like to get a hold of you later just to sell you stuff.
00:00:57.580 -->
00:00:59.740No, just to give you links.
00:00:59.920 -->
00:01:01.860So we cover a lot of stuff in the show.
00:01:02.160 -->
00:01:03.480You don't have to keep track of the links.
00:01:03.660 -->
00:01:11.900They're in the show notes, but they're also the links plus extra information and things you might need to know if you are new to Python or new to a topic.
00:01:12.580 -->
00:01:13.960Those are all in the email.
00:01:14.460 -->
00:01:19.980So you can go to pythonbytes.fm and sign up for the newsletter and we'll send that to you.
00:01:20.520 -->
00:01:22.320And that's all the intro stuff.
00:01:22.600 -->
00:01:26.240So, Michael, we got some exciting news for number one.
00:01:26.240 -->
00:01:27.700We have very exciting news.
00:01:27.840 -->
00:01:32.740And as part of this performance, Brian, I would like to recite The Raven by Edgar Allan Poe.
00:01:32.740 -->
00:01:33.760Oh, no, wait, this is not a performance.
00:01:34.320 -->
00:01:34.860And I don't want to do that.
00:01:35.160 -->
00:01:40.340I want to talk about Astral, actually, because this is a really interesting announcement from them.
00:01:40.740 -->
00:01:42.820Charlie and team are knocking stuff out of the park.
00:01:42.960 -->
00:01:49.020They're delivering big time on the tooling for Python packaging, managing Python, right?
00:01:49.180 -->
00:01:52.820all the layer that you build upon when you're writing applications, right?
00:01:53.200 -->
00:01:56.660So first they came out with Ruff for formatting and fixing issues.
00:01:57.160 -->
00:02:05.440Then they came out with uv, and then they upgraded uv to have its project management and Python management, not just alternate pip installs and so on.
00:02:05.660 -->
00:02:10.320And along all of that time, people have been saying, well, this is so amazing.
00:02:10.539 -->
00:02:14.940It's so fast and it does all of the things instead of piecing together tools.
00:02:15.500 -->
00:02:18.260But what if they rug pull us and we slip and we hit our head?
00:02:18.660 -->
00:02:20.100What if they go and do something else?
00:02:20.240 -->
00:02:25.300What if they start saying it's a half a cent per pip install or whatever, you know?
00:02:25.720 -->
00:02:26.380What are we going to do?
00:02:26.860 -->
00:02:32.760And Charlie has said that he's not planning on monetizing those types of things.
00:02:33.340 -->
00:02:34.980Instead, he wants to build on top of it.
00:02:35.100 -->
00:02:39.480So with this announcement, we get our first look at what that might be.
00:02:39.710 -->
00:02:42.840So it's interesting in and of itself, but I think it's also interesting in like,
00:02:43.260 -->
00:02:47.940this could be the thing that supports the stuff that people are really starting to depend upon.
00:02:48.360 -->
00:02:50.960And it's something called pyx, pyx.
00:02:51.400 -->
00:02:55.100I'm going to be interviewing Charlie on Talk Python in a couple of days.
00:02:55.800 -->
00:02:57.300By a couple of days, I think it's next week.
00:02:57.640 -->
00:03:00.940But pretty soon, I put a link to the event on the show notes.
00:03:01.100 -->
00:03:01.740People can check that out.
00:03:01.790 -->
00:03:03.100So we'll get the pronunciation.
00:03:03.280 -->
00:03:06.380I'm going to say pyx for now, like ty and uv and so on.
00:03:06.610 -->
00:03:08.100Unlike Ruff, not R-U-F-F.
00:03:08.700 -->
00:03:12.660So pyx, a Python native Python registry now in beta.
00:03:13.060 -->
00:03:15.180So here's the deal with pyx.
00:03:15.620 -->
00:03:33.560Think of this as an alternate PyPI, but not as a source of packages, not where, like when I publish something, I also have to publish the pyx, but more of a front end that adds a bunch of features or an intermediate layer, a middleware to PyPI itself.
00:03:34.210 -->
00:03:34.340Okay.
00:03:34.760 -->
00:03:58.080And at the moment, the plan is for this to be a full-on paid service for people that really need things like i really need my project to 100 be able to build some thing that's only available as a source distribution right how often have you pip installed something and most things just come down as a wheel and they come flying in but every now and then it'll stop and say
00:03:58.360 -->
00:04:08.879building something for 10 seconds the very first time before it gets cached then it goes yeah or longer yeah definitely potentially longer like i don't use it anymore we've talked about why
00:04:09.020 -->
00:04:44.820is uWSGI because they said please stop using our project we're not going to support it go find something else and we talked about that but that thing took forever to build but also if you're doing a gpu aware types of things you're doing a lot of stuff with pytorch or machine learning more broadly a lot of those things are huge and having the right platform built version is really really tricky okay so the idea is that uv and pyx are going to go together hand in glove So uv can work even better by having complete control over the back end as well.
00:04:45.630 -->
00:04:54.200They say there's some limitations that uv was able to solve, but not all of them because they don't control PyPI.org and its API and how things get built.
00:04:54.810 -->
00:05:01.280So the idea is making it easier to install PyTorch or CUDA-based libraries, that kind of thing.
00:05:02.180 -->
00:05:03.360It also solves the problem.
00:05:03.500 -->
00:05:07.040Why is everyone rebuilding the same packages over and over on their machine?
00:05:07.320 -->
00:05:09.340And what if those build tools are no longer the same?
00:05:09.800 -->
00:05:11.300Why did setup tools break our recent release?
00:05:12.340 -->
00:05:14.540How do we authenticate against our internal registry?
00:05:14.670 -->
00:05:18.900The other thing this is going to do is it's going to be a first class private registry.
00:05:19.500 -->
00:05:28.680So if you have a team, you're like, let's publish our data access layer, not to the world, but to our other people who are working on the projects, to our other applications, and so on.
00:05:29.020 -->
00:05:30.200So pretty exciting.
00:05:30.430 -->
00:05:32.300I think there's a lot of stuff going on here.
00:05:32.400 -->
00:05:32.980They're in beta.
00:05:33.090 -->
00:05:34.120You can join the waitlist.
00:05:34.350 -->
00:05:35.420You can get in touch with them.
00:05:35.780 -->
00:05:40.780It says, beyond the product itself, pyx is also an instantiation of our strategy.
00:05:40.890 -->
00:05:41.880And this is what I opened with.
00:05:42.280 -->
00:05:47.000Our tools, uv, Ruff, ty, et cetera, remain free, open source, and permissively licensed forever.
00:05:47.560 -->
00:05:53.600And this project is pretty interesting because it's a glimpse into how they're planning to make that possible.
00:05:53.880 -->
00:05:56.200Yeah, I'd be really curious to watch this.
00:05:56.420 -->
00:05:57.720I'm excited for a lot of reasons.
00:05:57.960 -->
00:06:00.660So let's say this is only a commercial offering.
00:06:01.780 -->
00:06:02.960It's a corporate sort of thing.
00:06:02.970 -->
00:06:03.840You have to pay to get it.
00:06:04.100 -->
00:06:10.040I'd be still okay with that because the alternatives, there's alternatives out there like JFrog Artifactory is around.
00:06:10.760 -->
00:06:23.040And there's other ways where you can, there's other products available to set up to mirror PyPI and do other things like as things come in, do like a security scan, your own security scans and things like that.
00:06:24.220 -->
00:06:30.460And so a mirror in front end, but also something that you can publish to internal, publish internal things to.
00:06:31.200 -->
00:06:32.280Those are really cool.
00:06:32.720 -->
00:06:34.400They're a little hard to set up though.
00:06:34.520 -->
00:06:38.260And I think I trust Astral to make this fairly easy for people.
00:06:38.980 -->
00:06:43.680It also would be cool if you want to test things out locally.
00:06:43.920 -->
00:06:58.920There's smaller businesses and smaller teams that aren't large corporations or even individuals that might have a need to try out what a repository might look like when you're doing those sorts of things or you're developing on an airplane or something, a local repo.
00:06:59.000 -->
00:07:05.020So I don't know if they're going to get down to the point where it's a, like a local person, like a free thing that you can just run on your own.
00:07:06.100 -->
00:07:07.580So it'll be interesting to watch.
00:07:07.590 -->
00:07:15.220I guess I'm okay with either if they want to keep it like paid only or something that, you know, small fry can use as well,
00:07:15.400 -->
00:07:16.560but I'm excited to watch.
00:07:16.880 -->
00:07:17.380I am as well.
00:07:17.740 -->
00:07:17.860Yeah.
00:07:17.920 -->
00:07:24.640There's, I think somewhere Charlie said maybe possibly there's a free version, but right now the plan is to be a paid project.
00:07:25.040 -->
00:07:25.180Yeah.
00:07:25.410 -->
00:07:25.540Yep.
00:07:25.720 -->
00:07:25.900All right.
00:07:26.020 -->
00:07:28.960That's all I got to say about that for now until I talk to Charlie and
00:07:28.980 -->
00:08:21.440more about i want to talk about lightstar a little bit there is an article called um uh where did i i missed it oh here it is sorry james bennett um has an article called lightstar is worth a look and i was looking through our past history a little bit and it looks like um we've talked about lightstar but it's been a while so you brought up um this was earlier this year i think talking about rewriting court um or rewriting talk python in court and lightstar is one of the things you looked at right so that was episode that was back oh that was last year november of 2024 so he asked client hello that was a good one um so we haven't talked about it a bit um so i was taking a look at it uh looking at Litestar i had never played with this and there is some interesting history around that it used to be uh star light like or something like that yeah it was not star
00:08:21.560 -->
00:08:22.840let star light.
00:08:23.340 -->
00:08:25.080And there was confusion, whatever.
00:08:25.500 -->
00:08:30.620Anyway, so this is an interesting James Bennett brought up Litestar is worth a look.
00:08:31.070 -->
00:08:36.680And he brought up like a lot of people do, if I'm going to do an API, why not FastAPI?
00:08:36.849 -->
00:08:42.940I mean, that seems like the obvious choice now for setting up an API or something.
00:08:43.280 -->
00:08:46.960And or a lightweight web framework. So why not?
00:08:47.940 -->
00:09:10.460There are a few reasons that he brought up. So one things was in scaling and not scaling in traffic, but scaling in, I want more than one file. I want a bunch of, I want my application in a bunch of files. And there was some frustration that he talked about with trying to figure out how to do that within FastAPI because there's the app dot.
00:09:10.800 -->
00:10:11.380And how do you have multiple routings in different files if you have one app? I don't know if this is easy or not. But he had some frustrations that it took him 40 pages into the documentation to the user guide to find that. However, it's kind of built in with Litestar is that you don't, it's not a top level app. You can, you can set it up, I guess, into multi-file, multiple files easier is one, one thing. The other thing was that FastAPI is tied to Pydantic. And I don't know if you can break that or not but um lightstar is not tied directly to pydantic and you can use it can use yeah it can use pydantic but it also has other options yeah uh um he he brings up um maybe attrs you could use attrs for validation which um some people forget that that's one of the cool things about attrs is it can validate things um or SQLAlchemy even can do um some of that so um Or a little combination of both, I guess.
00:10:11.860 -->
00:10:13.780Anyway, so that's interesting.
00:10:14.020 -->
00:10:18.500If you'd rather use SQLAlchemy for that or attrs, why not?
00:10:19.580 -->
00:10:23.460The third option, what is the third thing he brought up?
00:10:23.760 -->
00:10:25.260Is, I guess, just the architecture.
00:10:26.280 -->
00:10:27.140I had another note.
00:10:27.460 -->
00:10:32.140Anyway, it's interesting that there's another option out there.
00:10:32.440 -->
00:10:34.840So do you know more about Litestar?
00:10:35.100 -->
00:10:37.240I interviewed the guys from Litestar over on Talk Python,
00:10:37.310 -->
00:10:38.500so I know a little bit more.
00:10:39.160 -->
00:11:25.760not a ton more i would say one thing kind of a mental model i have about Litestar and i'm not sure how accurate this is but you know it's mine so i gotta have it is fast api is kind of flask esque in that it gives you enough to be have a bunch of cool building blocks but then you pick you build the other pieces and so on whereas Litestar seems to me a little bit more of the django philosophy where it comes with a bunch of batteries included like see all those little boxes down there look at all like the different pieces right it's got middleware it's got data stores it's got multiple it's got ORM integration caching like a lot of those things don't come off in that sort of stuff don't come with fast api which is both a good and a bad thing right like if it comes with
00:11:25.760 -->
00:11:29.800it but it's not what you want then it's just a hassle to battle against all the time yeah but
00:11:29.940 -->
00:11:37.400that's how i sort of perceive Litestars it's it's like fast api with more options and like more stuff included.
00:11:37.680 -->
00:11:37.940- I know.
00:11:38.340 -->
00:11:38.860- It is interesting.
00:11:39.100 -->
00:11:39.840Yeah, it's definitely interesting.
00:11:40.140 -->
00:11:40.340- Yeah.
00:11:41.120 -->
00:11:44.780- All right, also, also interesting is our sponsor.
00:11:45.460 -->
00:11:48.160Sentry is back and I want to tell you about them.
00:11:48.480 -->
00:11:51.600So this episode is brought to you by Sentry, of course.
00:11:52.000 -->
00:12:06.120It's been incredibly valuable for tracking down errors in our web apps, other code that we run, that's web apps, APIs, even the Talk Python mobile apps use it and send in errors when something goes wrong for somebody in some far flung place in the world.
00:12:06.540 -->
00:12:13.200Ian, I've told you the story more than once about how at Talk Python, I learned one user was encountering a bug through Sentry.
00:12:13.430 -->
00:12:16.080I fixed the bug and I let them know before they contacted me.
00:12:16.080 -->
00:12:17.440It was pretty wild, right?
00:12:17.820 -->
00:12:17.960Yeah.
00:12:18.240 -->
00:12:19.140So how does this work?
00:12:19.740 -->
00:12:31.120I'll walk you through a few simple steps on how you might add error monitoring and distributed tracing through some kind of e-commerce app that's got a JavaScript front end, Flask back end.
00:12:31.440 -->
00:12:35.740So if it's Flask on the front, React, sorry, Flask on the back end, React on the front end.
00:12:36.480 -->
00:12:40.480You wanna make sure there's no errors during some checkout process for an e-commerce page.
00:12:41.000 -->
00:12:45.060For me, anytime money and payments are involved, I always get a little extra nervous writing that code.
00:12:45.520 -->
00:12:46.440So here's what you do.
00:12:46.650 -->
00:12:51.320You enable distributed tracing and error monitoring in both your Flask backend and your React frontend.
00:12:51.640 -->
00:12:54.360Then you want to add enough context
00:12:54.700 -->
00:12:57.080to that frontend and backend action so they can be correlated.
00:12:57.560 -->
00:13:02.940And to do that, you enrich the spans, a Sentry concept with business context.
00:13:03.260 -->
00:13:07.920So in your React checkout, You wrap the submit handler in a start span and add information to that.
00:13:08.320 -->
00:13:09.700Then you want to see the requests.
00:13:09.810 -->
00:13:11.460You build a real-time Sentry dashboard.
00:13:11.710 -->
00:13:21.560You spin up one using span metrics to track key attributes, part size, checkout duration, and so on, giving you a single place to see both performance and error data.
00:13:21.880 -->
00:13:22.240That's it.
00:13:22.390 -->
00:13:29.200When an error happens, you open up the entry on the error on Sentry and you get end-to-end requests and error tracebacks and so on.
00:13:29.200 -->
00:13:32.740They also have a new product called Seer, which is C-E-E-R.
00:13:33.060 -->
00:14:03.100is a thing that looks at your app and uses LLMs to understand what's going wrong and possibly even suggesting, you know, here's actually what's causing that bug and it could even potentially do a PR and help you fix it, things like that. Really cool. So it's not just looking at the error, but even, you know, going further than that. So if your apps and your customers matter to you, you'll definitely want to set up Sentry like I have over at Talk Python and Python Bytes and so So visit pythonbytes.fm/sentry and use the code pythonbytes, all caps, just in a word.
00:14:03.280 -->
00:14:05.000That's pythonbytes.fm/sentry.
00:14:05.380 -->
00:14:06.540Use the code pythonbytes.
00:14:06.960 -->
00:14:08.760The link is in your podcast player show notes.
00:14:08.960 -->
00:14:10.300Thank you to Sentry for supporting the show.
00:14:10.560 -->
00:14:10.720Awesome.
00:14:10.820 -->
00:14:11.160Over to you, Ryan.
00:14:11.420 -->
00:14:11.520Yeah.
00:14:12.800 -->
00:14:13.620Sleeping on the job.
00:14:13.880 -->
00:14:13.980Sorry.
00:14:16.140 -->
00:14:19.400So for the next topic, I want to follow up from last week.
00:14:19.680 -->
00:14:22.460So just last week, I think it was last week.
00:14:22.660 -->
00:14:22.960Yeah.
00:14:23.540 -->
00:14:25.420444, Be Gone Python of Yore.
00:14:25.640 -->
00:14:26.480Two thirds of a beast.
00:14:28.840 -->
00:14:30.960That took me too long to figure that out.
00:14:31.800 -->
00:14:37.000So one of the things we talked about was an article called Stop Using Django's Squash Migrations.
00:14:37.520 -->
00:14:38.940And we had some feedback.
00:14:39.340 -->
00:14:45.560So from Bruno Alla said, hey, just a follow up and a plug for one of my own projects.
00:14:46.240 -->
00:14:49.040There is a project called Django Remake Migrations.
00:14:49.460 -->
00:14:51.300So that's really kind of what I want to talk about.
00:14:52.040 -->
00:14:52.960This looks pretty cool.
00:14:53.180 -->
00:14:55.080So it sort of does a lot of the stuff.
00:14:55.380 -->
00:15:00.140But one of the things that I like isn't just there's a tool that you can use to do a lot of this work for you.
00:15:00.230 -->
00:15:01.800You don't have to follow the step by step.
00:15:02.460 -->
00:15:04.740However, it's cool that it talked about the problem.
00:15:04.950 -->
00:15:08.460So it says a Django admin command.
00:15:08.820 -->
00:15:11.640There's a Django admin command to recreate all migrations in a project.
00:15:13.260 -->
00:15:16.920This new one is like squash migrations, but it's on steroids.
00:15:17.400 -->
00:15:30.240So it says the built in squash migrations command is great, but it only works on a single app at a time, which means that you need to run it for each app in your project and on a project with enough cross app dependencies that can be tricky.
00:15:30.660 -->
00:15:31.540Yeah, that sounds tricky.
00:15:31.940 -->
00:15:41.000So this command aims to solve this problem by recreating all the migration files in the whole project from scratch and mark them as applied by using the replaces attribute.
00:15:41.270 -->
00:15:48.640I don't know what that does, but there's some caveats like all migrations are marked as one as replaced once.
00:15:49.420 -->
00:15:55.300So I'm glad I'm using Git when I'm using any of this stuff so I could try it.
00:15:55.600 -->
00:15:57.600And if it doesn't work, roll it back.
00:15:57.840 -->
00:15:59.380But this looks pretty cool.
00:15:59.510 -->
00:16:08.240So I wanted to just shout out to people to maybe try this as well, if you want to try to remake your migrations easier.
00:16:09.000 -->
00:16:54.240While I was looking at this, I was like scrolling down, and it says the package was created with the copier template, and that rung a bell and it looked down and this was a while ago so michael brought up on this show talked about copier but that was back in 2021 so i'm going to go ahead and do a shout out to copier again because it looks pretty cool um copier is a is something like cookie cutter uh but it it's a cli app for rendering project templates but it looks kind of fun um uh so i'm going to check this out. I've got, I have some sort of project template needs coming up. And so I might take a look at this. They have a comparison too. So they're like, this is kind of like cookie cutter.
00:16:54.460 -->
00:17:16.760Yeah. They know it's kind of like cookie cutter. There's some differences here. They've got a table in the documentation. One of the things I kind of like is that the configuration files in YAML format instead of Jason for cookie cutter. I don't, I'm not really a fan of either, but if I got to handwrite stuff, I'd probably rather handwrite YAML files. So anyway, interesting to take a look
00:17:16.860 -->
00:17:40.760at. Nice. I think the biggest difference, other than I think being a little more maintained these days, is that it has, like with cookie cutter, you run a template, it generates a thing, and then you make changes to it, and that's it. With copier, you can apply, if there's a new version of the template, you can theoretically, at least, it has the option to try to apply a migration from the old version the new version.
00:17:41.120 -->
00:17:42.400Oh, that's cool.
00:17:42.660 -->
00:17:44.360Yeah, I think that's its biggest selling point.
00:17:44.600 -->
00:17:45.840Template updates, yeah.
00:17:46.280 -->
00:17:47.220That's actually awesome.
00:17:47.620 -->
00:17:47.740Yeah.
00:17:48.180 -->
00:17:50.100And it looks like it's composable too.
00:17:50.260 -->
00:17:57.920So you can like, if you might have different, like say for instance in a Django, you might have several applications that you would add.
00:17:58.080 -->
00:18:03.760You could use multiple copiers to pull an app, different apps into one application.
00:18:04.400 -->
00:18:06.980Right, add a CRM action or something, yeah.
00:18:07.240 -->
00:18:08.440Yeah, so interesting.
00:18:08.820 -->
00:18:10.000Very interesting indeed.
00:18:10.440 -->
00:18:10.500Cool.
00:18:11.000 -->
00:18:11.260All right.
00:18:11.560 -->
00:18:12.120On to the next one.
00:18:12.300 -->
00:18:13.460This is kind of like the Django show.
00:18:13.700 -->
00:18:16.240And one more Django shout out on top of this, by the way.
00:18:16.400 -->
00:18:25.960I'm going to be doing a happy birthday, happy 20th birthday Django panel with a bunch of the creators in an hour and a half, two hours from now.
00:18:26.280 -->
00:18:26.500Neat.
00:18:26.580 -->
00:18:29.940Now, if you're listening to the audio version, there's a good chance that's already over.
00:18:30.480 -->
00:18:35.680However, you can still either check out the live stream or in a few weeks, check out the Talk Python episode on it.
00:18:35.840 -->
00:18:39.060So keeping with that theme, Django Kronos.
00:18:39.350 -->
00:18:42.020This one's a quick little topic, but it's really cool.
00:18:42.270 -->
00:18:45.240So I want to know how fast my page is loading.
00:18:45.590 -->
00:18:52.880And I know there's the Django toolbar and all that, but here's a nice way to add more information about performance right into your browser.
00:18:53.100 -->
00:18:57.760So it's Django Middleware that shows you how fast your pages load right in your browser.
00:18:58.050 -->
00:19:01.100You simply add it as the first and last thing.
00:19:02.280 -->
00:19:06.440You know, the quick start says add it as your last installed app.
00:19:06.720 -->
00:19:10.540And it has a start and an end that has to be the first and last middleware.
00:19:10.840 -->
00:19:14.860So it gets the full picture of all the middleware actions and all that kind of thing.
00:19:15.800 -->
00:19:23.140I also would recommend saying probably show in production false, unless you really, really want to show in production, something like that.
00:19:24.040 -->
00:19:27.540But the idea is it just shows you how long did your middleware take to run?
00:19:27.900 -->
00:19:29.480How long did your view take to run?
00:19:29.660 -->
00:19:34.940How long did your SQL queries and commands take as part of the middleware, as part of the view?
00:19:35.400 -->
00:19:37.020And then how long did it take total?
00:19:37.580 -->
00:19:38.560And how many queries?
00:19:39.100 -->
00:19:43.720If you see the little screenshots of 7Q, 5Q, 12Q total, I'm guessing those are the number of queries.
00:19:44.320 -->
00:19:53.080One of the really big problems when you're working with ORMs, like Django has, but many, is they have lazy evaluation for relationships.
00:19:54.080 -->
00:20:01.540That can be tremendously slow because the programming model doesn't change if you do an eager query and join two things or you just use it.
00:20:02.060 -->
00:20:05.080It's really just about how the query was structured, not how you program against it.
00:20:05.460 -->
00:20:14.340So you might have, hey, I got a hundred things back from the list as one query, and then I loop over it and I interact with a field where each one of those is doing another query, a hundred more.
00:20:14.680 -->
00:20:18.440So 101 queries, hence they typically called the N plus one.
00:20:18.540 -->
00:20:19.460So you would see something like that.
00:20:19.500 -->
00:20:22.000You'd be like, whoa, the view is doing 107 queries.
00:20:22.090 -->
00:20:23.540I think I got two things, what's happening?
00:20:23.960 -->
00:20:26.400Well, N plus one, some version there probably.
00:20:26.800 -->
00:20:33.620Anyway, if this is interesting to you, It's not super big in terms of popularity, but it's also pretty straightforward and simple.
00:20:33.990 -->
00:20:35.000And yeah, people might like it.
00:20:35.200 -->
00:20:37.440- Remind me, where does the information pop up?
00:20:37.580 -->
00:20:41.000Is it in the browser when you're developing or something?
00:20:41.090 -->
00:20:43.800- I think it's at the bottom of the page.
00:20:43.930 -->
00:20:47.880I haven't installed it and tried it, but it's somewhere in the page as part of it.
00:20:47.920 -->
00:20:48.080- Okay.
00:20:48.390 -->
00:20:48.500- Yeah.
00:20:49.340 -->
00:20:57.120So basically, I believe what it does, it actually gives your template, your Django template, these pieces of information and you show them how you want.
00:20:57.220 -->
00:21:01.900So it gives you middleware CPU time, SQL time, view, count total time.
00:21:02.080 -->
00:21:03.760Basically the stuff that was on the screen.
00:21:04.020 -->
00:21:05.140So you can put it in.
00:21:05.520 -->
00:21:09.920It provides it as data values, and then you would put it into your view as you see fit.
00:21:10.200 -->
00:21:10.280Right.
00:21:10.450 -->
00:21:11.240I believe that's how it works.
00:21:11.500 -->
00:21:11.700Okay.
00:21:12.100 -->
00:21:12.180Cool.
00:21:12.560 -->
00:21:12.840That's neat.
00:21:14.320 -->
00:21:14.500Indeed.
00:21:14.690 -->
00:21:16.700Well, those are our topics.
00:21:17.820 -->
00:21:20.260I have a little bit of an extra.
00:21:20.710 -->
00:21:21.100Go for it.
00:21:21.240 -->
00:21:21.580All right.
00:21:23.140 -->
00:21:24.600I'm going to go back in time a little bit.
00:21:24.860 -->
00:21:30.320And so Test and Code is a podcast I started in August of 2015.
00:21:31.160 -->
00:21:32.180So it's August.
00:21:32.680 -->
00:21:35.040So it's now, it's August 20.
00:21:35.040 -->
00:21:36.060It's almost two days.
00:21:36.580 -->
00:21:38.640In two days, it'll be like 10 years.
00:21:39.680 -->
00:21:40.760I think that's enough.
00:21:40.880 -->
00:21:42.520I'm looking at like episode two.
00:21:42.960 -->
00:21:43.900Episode one was terrible.
00:21:43.960 -->
00:21:45.180So I deleted it a long time ago.
00:21:45.460 -->
00:21:48.940So episode two is a pytest versus UnitTest versus Nose.
00:21:48.940 -->
00:21:51.120And I didn't even capitalize pytest correctly.
00:21:51.740 -->
00:21:52.220That's bad.
00:21:52.280 -->
00:21:57.900And Nose is just, if I were to redo this, it would just say, don't, just pick by test.
00:21:59.260 -->
00:22:00.360There's one option, really.
00:22:00.780 -->
00:22:03.760Anyway, unit test is fine also, but let's get real.
00:22:04.020 -->
00:22:04.920Don't use Nose.
00:22:06.100 -->
00:22:07.360So what is this?
00:22:07.720 -->
00:22:08.740Why am I bringing this up?
00:22:08.900 -->
00:22:17.180Well, I just released on Friday, episode 238, So Long and Thanks for All the Fish, where I announced that I am no longer doing testing code.
00:22:17.440 -->
00:22:19.100So closing the book on that chapter.
00:22:19.560 -->
00:22:24.380I listened to that episode and yeah, I think what I'll say is congratulations.
00:22:24.640 -->
00:22:29.16010 years and 238 episodes is quite a run and those things will be around.
00:22:29.300 -->
00:22:30.860People can listen to them and enjoy them.
00:22:31.080 -->
00:22:31.280Yeah.
00:22:31.420 -->
00:22:34.360So that's another thing is I'm seeing.
00:22:34.620 -->
00:22:40.200I'm not sure how long I'll leave it live because podcast hosting is something you have to pay for.
00:22:40.400 -->
00:22:41.820So I am.
00:22:42.000 -->
00:22:42.700You know what?
00:22:42.820 -->
00:22:48.600I say you take it, write a little web scraper and just generate a static site and just leave it there.
00:22:48.660 -->
00:22:54.960that's not something I might be able to give you work how about that actually so that yeah but the
00:22:55.140 -->
00:23:07.360point was to remove work from my plate but you know we'll see all right can't leave that up in the air um all right what you got for us do you have any extras yes I have some extras let me get it ready
00:23:07.940 -->
00:23:19.080so we have python 3 13 6 big question will this be the final 3 13 before 3 14 probably not but It's plausible, right?
00:23:19.360 -->
00:23:23.140We're talking October, which is sadly not that far away.
00:23:23.530 -->
00:23:24.380Not ready for rain.
00:23:24.670 -->
00:23:25.400Not ready for it.
00:23:26.360 -->
00:23:28.740Anyway, 3.13.6 is out.
00:23:28.740 -->
00:23:30.680And there's actually a lot of changes.
00:23:30.910 -->
00:23:35.980If you flip through the library, I don't know how many pages that is, but we're talking a lot of pages.
00:23:36.270 -->
00:23:42.180So there's actually a ton of changes here that you might want to check out, you know, like little security fixes and other stuff.
00:23:42.460 -->
00:23:43.400Does it have that zip?
00:23:44.000 -->
00:23:50.060There was some kind of zip issue where you could trick it into do.
00:23:50.120 -->
00:23:51.560And I don't think that was in Python.
00:23:51.780 -->
00:23:53.280I think that was in pip.
00:23:53.660 -->
00:23:55.180And uv also had it.
00:23:55.280 -->
00:23:58.940So update your uv, by the way, folks, as well, which is uv self-update.
00:23:59.160 -->
00:23:59.460Easy enough.
00:23:59.700 -->
00:24:00.620Anyway, this is out.
00:24:00.860 -->
00:24:04.900Because of our sweet Docker setup, I just did a rebuild on Python Bytes.m.
00:24:05.260 -->
00:24:07.240And it said uv install Python.
00:24:07.860 -->
00:24:11.080And we have 3.13.6 powering everything all of a sudden.
00:24:11.320 -->
00:24:11.580Very nice.
00:24:12.020 -->
00:24:12.960Anyway, quick and easy.
00:24:13.340 -->
00:24:13.440Yeah.
00:24:13.620 -->
00:24:19.660on top of that the final 13 the final countdown i was just listening to that song uh i have this
00:24:19.730 -->
00:25:31.800really cool script and i think this is kind of it's kind of interesting and please don't write me and tell me other things are out there that do this because i know there are some that sort of do this but it's interesting in and of itself but it's also interesting as we get better and better llm and agentic coding tools i just say instead of just like depending on something that has 100 features and I'm going to take one or two of them and then deal with that. I just want this one thing. Could I just ask to have that one thing created? The answer is probably yes. So I wanted something that would auto activate Python virtual environments built with uv, named like I like, exactly as I navigate around my shell. So I asked Claude, I think, something like that. And it said, sure, here's a cool little bash script that as you enter a folder that either itself has a virtual environment or somewhere up in the higher hierarchy of it as a virtual environment it'll just activate it and if you leave that portion of the directory tree it'll go back and unactivate it and i know that dur env does some things along these lines but like i said i just like i think it's really cool you can just say really all that needs to be is like 35 lines of bash and then it never changes so i put up i decided someone was like oh that's really cool is that happening i'm like i'll just
00:25:31.880 -->
00:25:39.840put that up as a gist and people can check it out i like it also something small that you can change if it's not quite what you want, change it.
00:25:40.090 -->
00:25:40.200Exactly.
00:25:40.640 -->
00:25:44.160I'm not looking for something that solves every problem for every programming language
00:25:44.550 -->
00:25:45.320in the most.
00:25:45.900 -->
00:25:47.840I just want this one little feature.
00:25:48.290 -->
00:25:52.760And I don't really, to be honest, I don't know enough Bash to do this really well.
00:25:53.040 -->
00:25:53.920But guess what?
00:25:54.230 -->
00:25:55.680Either chat or cloud sure knows it.
00:25:55.850 -->
00:25:56.560And it took care of it.
00:25:57.160 -->
00:25:58.440So I'm really enjoying that.
00:25:58.700 -->
00:26:06.660Yeah, I'm totally going to use this, although I'm going to change venv to.venv because Brett - The Canon convinced me that the dot is good.
00:26:06.840 -->
00:26:09.580- I got tons of respect for Brett, but not my thing.
00:26:10.420 -->
00:26:17.460I want to be able to look either via LS or in the macOS Finder and see that it has a virtual environment.
00:26:18.280 -->
00:26:19.660And you can if it's a dot, right?
00:26:19.930 -->
00:26:21.300So anyway, fair enough.
00:26:21.500 -->
00:26:25.140I want to be able to look at it and go, yep, it absolutely has a virtual environment, right?
00:26:25.240 -->
00:26:27.760'Cause that tells me what my next action needs to be.
00:26:28.000 -->
00:26:32.500All right, I just, I spent a long time this summer writing up this huge long post.
00:26:32.760 -->
00:26:36.700I don't know if it'll actually tell us how many minutes of reading time it is, if I ask.
00:26:37.260 -->
00:26:41.16024 to 34 minutes of reading time for this article that I wrote.
00:26:41.480 -->
00:26:41.700Okay.
00:26:41.860 -->
00:26:44.560And it's called The State of Python 2025.
00:26:45.030 -->
00:26:46.960I wrote this in partnership with JetBrains.
00:26:47.460 -->
00:26:59.940And it takes the PSF JetBrains survey results and does like a ton of analysis on it and predictions and concrete actions people could take based on the trends that we're seeing and so on.
00:27:00.220 -->
00:27:01.680So I'll put that here now.
00:27:01.840 -->
00:27:08.660I think I might make this one of next week's items and we can dive into some of the trends and recommendations and you can tell me how I'm wrong or right.
00:27:10.040 -->
00:27:14.380But it just came out this morning, so I thought I'd go ahead and just throw it out there as an extra for now.
00:27:14.640 -->
00:27:14.800Cool.
00:27:15.080 -->
00:27:15.220Yeah.
00:27:15.560 -->
00:27:24.720Next, if you run local LLMs, as I do, and there's a really interesting option, you can now run OpenAI's.
00:27:25.100 -->
00:27:26.200Well, first of all, hey, guess what?
00:27:26.400 -->
00:27:31.640OpenAI has a public open weights model you can use and you can run it locally.
00:27:31.820 -->
00:27:39.680So I'm running here in LM studio in developer mode and programming against the GPT OSS 20 billion parameter model.
00:27:40.040 -->
00:27:40.560How cool is that?
00:27:40.880 -->
00:27:41.320That's pretty cool.
00:27:41.640 -->
00:27:41.700Yeah.
00:27:41.940 -->
00:27:42.300So I have some,
00:27:42.460 -->
00:27:43.100maybe, I don't know.
00:27:43.820 -->
00:27:44.300It's super cool.
00:27:44.300 -->
00:27:47.140I have some other things that I created, like little utilities.
00:27:47.210 -->
00:27:49.620I'm like, Hey, I want this utility to work and it needs an LM.
00:27:50.080 -->
00:27:53.520And I knocked it out real quick in combo with some agentic coding.
00:27:54.000 -->
00:27:57.180And it was using when, which was pretty good.
00:27:57.210 -->
00:28:00.640But then when this came out, I'm like, let me try this and see if it'll give me better answers.
00:28:01.160 -->
00:28:01.340Sure enough.
00:28:01.660 -->
00:28:04.900So now I'm just running this locally on my Mac mini and talking to it.
00:28:04.900 -->
00:28:05.780And it's pretty good.
00:28:06.000 -->
00:28:06.920So that's a cool option.
00:28:06.930 -->
00:28:09.420You run it in Olama or other places as well.
00:28:09.720 -->
00:28:17.760And finally, just remind people that we just released the Just Enough Python for Data Scientists course for $29 over at Talk Python.
00:28:18.060 -->
00:28:27.380So you're getting started in your data science journey or you feel like you've been doing it for a long time, but you just don't quite have the software engineering techniques and tools and so on.
00:28:27.620 -->
00:28:28.140Check this out.
00:28:28.390 -->
00:28:29.460Just talkpython.fm.
00:28:29.570 -->
00:28:30.020Click on courses.
00:28:30.460 -->
00:28:30.780Be right there.
00:28:31.220 -->
00:28:31.860That's it from extras.
00:28:32.410 -->
00:28:32.500Awesome.
00:28:33.860 -->
00:28:34.600That's all over extras.
00:28:34.920 -->
00:28:36.740Do we have, do you have something funny for us?
00:28:36.850 -->
00:28:39.320I have a quick follow-up before we do from Pat Decker says,
00:28:39.430 -->
00:28:40.520I saw your post on Bluesky.
00:28:40.820 -->
00:28:41.900Listen to 238.
00:28:41.930 -->
00:28:42.580I agree with Michael.
00:28:42.800 -->
00:28:44.240Congratulations on 10 years, Brian.
00:28:44.590 -->
00:28:44.940Thank you.
00:28:45.330 -->
00:28:45.660Thanks, Pat.
00:28:46.020 -->
00:28:46.200Indeed.
00:28:46.700 -->
00:28:46.820Okay.
00:28:47.040 -->
00:28:47.900Yes, we have a joke.
00:28:48.460 -->
00:28:48.940Let's check it out.
00:28:48.970 -->
00:28:54.700This one, you know, people don't like if I, they don't like generally when, when one language bashes on another.
00:28:54.710 -->
00:28:56.580Well, some of them do, but not, not generally.
00:28:56.870 -->
00:29:00.080So keep folks, before I show you this joke, it's supposed to be lighthearted.
00:29:00.400 -->
00:29:01.740Please don't, Don't email us, tell me.
00:29:02.160 -->
00:29:05.900So the joke is, Python is better than Java, says someone.
00:29:06.340 -->
00:29:07.600Another person says, prove it.
00:29:08.400 -->
00:29:19.820So the original person fires up Python, creates two strings, one named Python, one named Java, and then asks, as writing in the interpreter, Python greater than Java as strings?
00:29:20.240 -->
00:29:20.400True.
00:29:20.900 -->
00:29:21.480True, says Python.
00:29:22.820 -->
00:29:23.560It's greater.
00:29:23.880 -->
00:29:24.440Yeah, sure.
00:29:25.840 -->
00:29:26.020Truth.
00:29:26.300 -->
00:29:26.540It's true.
00:29:27.220 -->
00:29:27.600There you have it.
00:29:27.680 -->
00:29:28.760Anyway, I just thought that was funny.
00:29:29.100 -->
00:29:29.340Yeah.
00:29:29.620 -->
00:29:31.780It's too bad that Python doesn't have a better operator.
00:29:32.340 -->
00:29:34.000Not necessarily greater, but just better.
00:29:34.440 -->
00:29:34.680Exactly.
00:29:36.640 -->
00:29:37.540Well, there it is.
00:29:38.120 -->
00:29:39.000Yeah, that's the joke.
00:29:39.600 -->
00:29:39.980All right.
00:29:40.320 -->
00:29:40.380Cool.
00:29:40.740 -->
00:29:41.880Well, thanks again.
00:29:42.180 -->
00:29:43.040Thanks, everybody, for listening.
00:29:43.660 -->
00:29:44.660And see you next time.
00:29:44.900 -->
00:29:45.040Yep.
00:29:45.260 -->
00:29:45.540See you later.
00:29:45.880 -->
00:29:46.020Bye, all.