Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.
This is episode 434, recorded June 2nd, 2025.
I'm Michael Kennedy.
And I am Brian Okken.
And I am super happy to say that this episode is brought to you by DigitalOcean.
They've got, obviously, a bunch of amazing servers, but some really cool Gen.AI features we want to tell you about as well.
So we're going to be telling you about that later.
The link with a $200 credit is in the show notes.
So no spoiler there.
If you would like to talk to us on very social things, tell us about what we might want to cover, give us feedback on what we have.
Links to our Mastodon and Blue Sky accounts are at the top of the show notes as well.
You can join us live right here, right now on YouTube.
Almost always Monday at 10, unless something stirs up the calendar and breaks that.
But we try to do Monday, 10 a.m. Pacific time.
All the older episodes are there as well.
And finally, if you want an artisanal, handcrafted, special email from Brian with extra information about what's going on in the show.
Well, sign up to our mailing list.
And Brian, some people have been saying that they had been having trouble receiving emails.
Like they signed up and they didn't get them.
Yeah.
Well, that's because there's a bunch of jerks on the internet and they make it hard to have nice things like email that works.
So it's like so many spam filters and other things that I've done some reworking.
And I think some people who signed up probably will start getting email again.
But basically their email providers had been saying, hey, you're sending from an IP address that has previously sent spam.
Blocked.
Well, we use Syngrid.
Syngrid just round robins us through a whole bunch of different IP addresses.
And if we happen to get one that previously got flagged, well, then you might get unsubscribed from an email list.
How much fun is that?
So I've done a bunch of coding behind the scenes to try to limit those effects and just send it again next time because it'll be a different IP address.
Ah, jerks.
So,
that is the spammers.
Yeah, thanks.
And I guess with that, we're ready to kick it off.
What you got?
Well, I've been speeding up some test suites.
So I'm interested in this blog post on trail of bits.blog.
It's a trail of bits blog.
And I think we've covered some stuff from them before, but
anyway.
Yeah, usually they're a security company.
They do really interesting research into a lot of security things.
Oh, really? Okay.
Well, apparently one of the things they've worked on is, or at least they're writing about, is making, yeah, it says trail of bits collaborated with PyPI several years ago to add features and improve security defaults across the Python ecosystem.
But they also, today
we'll look at
equally critical aspect of holistic software security, test suite performance.
So there was some effort to speed up the test suite.
And this is incredible.
So one of the reasons why I'm covering this is to speed up test suites.
But also I often get questions about is pytest robust enough to test a large system?
And yes, it is.
And I actually don't even think I'd, I mean, Warehouse is a decent size.
Apparently they've had the current, or the test suite as I've read this writing is 4,700 test count.
The test count was 4,700.
It's quite a few tests.
And so Warehouse, Paras, PyPI.
There's a nice graph on the blog post showing the time spent.
So they went from 163 seconds.
So that's what, two minutes and almost two and a half,
three minutes?
Yeah, almost three minutes.
Almost three minutes down to 30 seconds.
So this is a nice speed up.
And even as the test counts were going up, the time spent was going down.
So how did they do this?
The big chunk of the performance improvement was switching to pytest XDist.
So XDist is a plugin by the pytest team, by the core team, or at least that's who's maintaining it.
And that is 67% of the reduction.
What it does is it allows you to run it on multiple cores.
So like I think in this one, they had a 32-core machine.
They can run it
on multiple cores.
So you use multiprocessing?
Yeah.
Threading, right, yeah.
Yeah, it is multiprocessing.
I think there's some configuration there that you can fiddle with, but mostly it's multiprocessing.
So there is some overhead in doing that, So you wouldn't want to try to speed up a really fast, already fast, small test.
The test suite would go slower with XGIS.
But anyway, this is a larger one.
But one of the things I like about this is because it's not a free lunch for XGIS because it's not always easy to split up your test suite like this one.
So they were talking about parallelizing the test execution.
You just say num process equals auto or dash in equals auto, and that just runs it on a bunch.
It doesn't really work if you have things that are a shared resource like a database.
So they also talked about setting up database fixtures such that each test worker gets its own isolated database.
So they kind of show some of the code on how to do that.
But this is open source code, so you can go check out the entire thing if you want.
The other thing that you get with XDIST is very tertiary reporting.
So they increase the readability by using pytest Sugar.
And I don't use pytest Sugar a lot, but it sure is popular.
And it gives you little check marks.
But one of the things it does is makes XDIST even more verbose.
But it's kind of a nice green check marks.
It feels good. It's better than the little dots.
Anyway, so that was a massive improvement with X-Disk, but that's not all.
Python 3.12 added the ability for coverage.py to run faster by using the sysmonitoring module, and NedBatch Elder implemented that a while ago.
So they turned that on with a coverage core environmental variable, and that sped things up quite a bit as well, another 53% time reduction.
then test discovery phase this is an easy one didn't didn't increase time that much but it's just everybody should do this it's one line config to say where are my tests so that's a good one and then a last one is unnecessary import overhead is this kind of an interesting thing that I was like how did they do this and through testing and they're using a thing called dd trace And that is through, what is DD trace through?
Datadog library.
But what, what it's, I don't know what it does really, but I just checked it out.
I'm like, why, how are they?
I looked at the pull request to see how they did it.
And they're using a flag dash P that is, allows you to turn off plugins, either turn on or turn off plugins in your test suite.
And DD trace doesn't look like it's a high test plugin, but it does have one.
So I took a look.
DDTrace comes with a couple of pytest plugins.
So that makes sense that those are going to pull in DDTrace when the plugins get read.
So anyway, interesting side tangent right there.
But really interesting read on how to speed up test suites.
And this has reminded me that I really need, I've got a whole bunch of tricks up my sleeve too.
I'd like to, I need to start a how to speed up your test suite post or series of posts.
Yeah, that's super interesting.
Good stuff.
me ideas.
Yeah. Anyway, and I'll have actually my next top, the next topic we talk about later in the episode will be around speeding up test suites as well. So,
okay. Well, it's all about speed this week. Speed. Test speed. All right. This one is super interesting. And so I came across, I don't even see this. I don't spend that much time on X. Not necessarily because I've got like some vendetta against X, although you would know that for me, not reviews on, I think it was on Doc Python. Somebody absolutely like went, is having like a moment.
Because I said, hey, Mastodon's cool.
Oh my gosh. Anyway,
no,
I don't spend that much time
on there because I just find that like, I feel like the algorithm just hides my stuff and I don't get into really conversations or engagement.
So that said, I ran across this thing that is super interesting from Pietro Charano.
Charano? And it says, people aren't talking enough about how most of open AI, aka ChattiePT, Tech stack runs on Python.
And there's this screenshot of a newsletter that talks about it.
So the tech stack.
This is super interesting.
Python.
Most of the product's code is written in Python.
Frameworks.
FastAPI.
The Python framework used for building APIs quickly using standard Python type hints and Pydantic.
Talks about it.
C for parts of the code that need to be highly optimized.
The team uses lower level C for the programming language.
And then something called Temporal for asynchronous workflows.
Temporal is a neat workflow solution that makes multi-step workflows reliable even when individual steps crash without much effort by developers.
I actually don't know what Temporal is.
Maybe it's Python.
It probably is.
It sounds like it.
Just to remind me, this is OpenAI's tech stack?
Yes.
Okay.
Did some searching and I came up with the original article there.
And this comes from a conversation around building ChatGPT's images, the image generation stuff, where you say, make me an infographic about what I've been talking about or whatever, which is incredible these days.
So the article is entitled Building, Launching, and Scaling ChatGPT Images.
It's OpenAI's biggest launch yet with 100 million new users generating 700 million images in the first week.
But how is it built?
Let's talk about Python, right?
So Python, FastAPI, C, and Temporal.
How cool is that?
For people who are like, well, it's fun to use Python for these toy projects, but it's an unserious language for unserious people who don't build real things.
Or is it?
100 million new users in a week.
That's pretty epic.
Well done, FastAPI.
Well done, new versions of Python.
All these things.
I got to know, what is Temporal?
Is this what it is?
Probably not even a, you know, a double execution.
This is written in Go, so apparently Temporal is probably not.
Anyway, isn't that interesting?
It's always fun to have a data point.
Yeah.
I like that.
I think there's a lot that we don't even know.
People don't talk about that are written in Python and FastAPI now.
So it's a different world.
What
else is
nice?
DigitalOcean.
DigitalOcean is awesome.
Yeah, DigitalOcean powered Python Bytes for a very long time.
I love DigitalOcean.
I highly recommend them.
But you got something specific to say, don't you?
I do.
This episode of Python Bytes is brought to you by DigitalOcean.
DigitalOcean is a comprehensive cloud infrastructure that's simple to spin up even for the most complex workloads.
And it's a way better value than most cloud providers.
At DigitalOcean, companies can save up to 30% off their cloud bill.
DigitalOcean boasts 99.99% uptime SLAs and industry-leading pricing on bandwidth.
It's built to be the cloud backbone of businesses small and large.
And with GPU-powered virtual machines plus storage, databases, and networking capabilities all on one platform, AI developers can confidently create apps using that their users love.
Devs have access to the complete set of infrastructure tools they need for both training and inference so they can build anything they dream up.
DigitalOcean provides full-service cloud infrastructure that's simple to use, reliable no matter the use case, scalable for any size business, and affordable at any budget.
VMs start at just $4 a month and GPUs under $1 per hour.
Easy to spin up infrastructure built to simplify even the most intense business demands.
That's DigitalOcean.
And if you use DO4 bytes, you can get $200 in free credit to get started.
Take a breath.
DigitalOcean is the cloud that's got you covered.
Please use our link when checking out their offer.
You'll find it in the podcast player show notes.
It's a clickable chapter URL as you're hearing this segment, and it's at the top of the episode page at pythonbytes.fm.
Thank you to DigitalOcean for supporting Python
Bytes.
Indeed. Thank you very much.
All right. Let's see what we got next, Brian.
Okay.
PyCon. Neither of us made it a PyCon this year, did we?
That's too bad.
Yeah.
But, you know, c'est la vie.
Sometimes that's how it is.
And I would venture that most of the people listening to this show didn't.
because if everyone listening to the show attended PyCon, it would sell out many times over.
So that would mean most people here are very excited to know that they can now watch these talks.
Most of them.
There's something going on with 40 of them, but there's a bunch, there's what, 120 of the talks are online here.
So I'm linking to the playlists for the PyCon videos, which is pretty cool.
This came out a lot quicker than it did last time.
Last time it was months until they published these, which was unfortunate.
But, you know, this is like a week or something after the conference.
So that was really good.
That's incredible speed.
Yeah.
Yeah, yeah, yeah.
And I pulled up something I want to highlight.
It's too hard to navigate the playlist.
So I'm just going to read them out that I like here.
So I found the keynote by Cory Doctorow to be super interesting.
It was basically how, like, going deep into his whole in poopification stuff that he's been talking about, which is a really, really interesting idea.
A little hard to hear because mask, but you know, it's okay.
Still worth listening to.
There's one talk entitled 503 Days Working Full-Time on FOSS, Lessons Learned, which sounds really interesting.
There's Going from Notebooks to Scalable Systems with Katherine Nelson.
And I just had her on Talk Python.
So for all of these, I'm linking them in the show notes.
And when I say, and on Talk Python, I linked over to that episode or that video or whatever as well, because her talk is not quite published yet. It's just recorded in advance. Unlearning SQL. Doesn't that sound interesting?
Like most people are trying to learn SQL. Why would I unlearn it? The most bizarre software bugs in history. It was interesting. The PyArrow Revolution in Pandas. I also did an episode with Reuben Lerner about that. What They Didn't Tell You About Building a JIT Compiler in CPython by Brant Booker. Also did a Doc Python episode about that and linked to that one. This one's cool from Hennick, design pressure, the invisible hand that shapes your code.
He's got some really interesting architectural ideas, so super cool.
Marmo, the notebook that compiles Python for reproducibility and reusability, and I talked about an episode about that.
GPU programming in pure Python, and I talked about an episode about that.
And finally, scaling the mountain, a framework for tackling large tech debt, large scale tech
debt.
Oh, that looks interesting.
Don't all those talks sound super interesting.
Yeah.
So
I've linked all of them.
I pulled them out.
Y'all can check them out if you want.
They're in the show notes.
The most bizarre software bugs in history.
Total clickbait, but I'm going to watch it this afternoon.
I've got to.
Exactly.
I can't wait to watch it.
Yeah, no, it's fun.
All right.
Over to you.
Okay.
This is an interesting header on this, but table of contents, expand.
Anyway, I just wanted to find some posts to talk about this because it's a technique that I use for speeding up test suites.
And it wasn't covered in the last posts that we talked about.
So optimizing Python import performance.
So in the previous discussion, we talked about removing, using Dashp and pytest to remove plugins that might remove imports of things you don't need.
What if there's things that you do need, but not all the time?
So one of the things I want to talk about is this test collection.
So like the other one, they used Python-X import time.
And you use it by just like running, like you can run your app or you can run pytest afterwards.
And you can find out, it prints out a list of, this has been an instance Python 3.7, I think.
But it prints out a list of all of the imports and how long it took to import them.
And it's a little bit hard to parse because it's sort of like a text-based tree level thing.
But it's not bad.
And looking at all of that, you can try to find out which ones are slow.
So one of the techniques is lazy imports.
And this is a weird quirk about Python that I didn't learn until recently, was that when you import something, normally we put the imports at the top of the file.
But when you import a module, it imports everything that that module imports also.
So if you don't, if the things that you're depending on are not really part of the, if the user of it doesn't really need to import that stuff, like just for imports, you can hide that import within a function and it still acts globally.
So like in this example, it says process data, import pandas as PD.
It's only imported when the function runs.
But even after that function, that pandas is available in the module for everything else also.
Kind of a weird quirk, but it works good.
And I'm just going to tie this together to testing right away.
Tests, test collection, at test collection time, pytest imports everything.
So if you don't, and you probably don't need to import any of your dependencies at collection time.
So I look for any expensive imports and move those into a fixture, usually a module level auto use fixture to get that import to only run when the test runs, not when you're doing collection.
So that's an important trick.
Avoiding circular imports.
So I just thought that, so I, hopefully you're already doing this already, but it says circular imports force Python to handle incomplete modules.
They slow down execution and cause errors.
I knew they caused errors.
I didn't understand the just slow down execution part.
So there might be a way to, like there might be some legitimate cycles, sort of, but get rid of them.
That's weird.
It does sometimes have to, you have to restructure code.
The third thing is keeping dunder and nits very light.
And this is a tough one for pytest tests and stuff because sometimes I have a tendency to shove things into dunder and nits, and especially for importing everything, but keeping those dunder and nits files as clean and fast as possible.
So there's other things in this article as well, but those are the three that I really hit on to try to speed up test suites as cleaning up the import time.
So,
yeah, that's really cool.
And you might wonder, like, well, what is slow?
What is fast?
How do you know?
Well, there are tools to import profile imports.
We've talked about them before.
I don't remember which one we covered, but there's one called import underscore profile.
Cool.
I was looking for that.
Nice.
Yeah.
And
so you can just say run my code dash m import profile, and then you can just give it the things that you would be importing, and it gives you a nice little timing of them.
And probably a lot of them are super slow and you're wasting your energy to deal with trying to optimize that stuff.
But some are fast.
I mean, some are not fast.
And some use a lot of memory and different things like that.
So this is actually pretty interesting to see how that all works, right?
Yeah.
And actually, so when I was doing some optimization for a big test suite recently, you got to measure because there were things that were fairly large packages that I just assumed they were going to be slow.
But they had their import system optimized already.
So those ones don't really, some packages that seem large like pandas or something might actually be pretty quick.
But it looks like it's, in this example, wasn't.
But like NumPy, it does a lot, but it's a pretty, it's a faster import.
So interesting.
It also depends, you know, how are you, you only import it once per process, right?
it's not going to be imported over and over again.
So if it's 100 milliseconds, is it worth worrying about?
Maybe,
maybe not.
And also with throwing things away, like let's say you've got, so one of the things often in a test requirement or development requirements file or something or in your test requirements, there might be, so there's two sets of things that I look at often.
They're pytest plugins that are useful for developers to run locally, but they're not really needed in CI.
So you can like take them out in CI.
And then the reverse is like in CI, we often have, I often have like a reporting system.
Like I might export all the data to a database and have some plugins to handle that.
And that's not needed locally.
So turning those off locally so that you can have a little faster run.
So things like that.
So anyway, speeding up testing is a good thing.
Yeah, absolutely.
It's all right.
Extras, you got extras?
I got, yeah.
So I've got a couple extras.
how about you?
Let's go with yours first. I got a few too. Okay.
So this is pretty quick. So this is from Hugo Peps and Co. A little bit of history about where PEP came from. I've just been using it since using the word, but apparently Barry Warsaw came up with the acronym and he calls it a backronym. He liked the sound of PEP because it's peppy before he came up with the Python enhancement proposal acronym so that's an interesting thing but that also takes a look at since then there's been a lot of improvement proposals and enhancement proposal like acronyms all over the place in different different communities so this is interesting like astro pie proposals for enhancement and you totally know that they intentionally reverse those so they can make ape. That's great.
Yeah, that's fun.
The second one is pythontest.com.
My blog has got a fresh coat of paint. It's got light and dark modes, but it's more colorful now. It also makes it glaringly obvious that I don't blog as much as I'd like to.
The fourth oldest post is from January of 2024.
Oops, gotta get on that.
But one of the neat things I like about it is, and part of it is, I didn't really like my theme so i wasn't really vlogging much so
i think i like it better hopefully i will and it's still running on you go or what's it running on yeah
it's hugo with um in this i don't even it's a javascript based search thing um and it it's pretty zippy this is all just like anyway
i like yeah very cool uh
one of the what was it i was gonna one there was one change that i'm hopefully maybe might change is the light mode for code highlighting looks fine, but it's a little hard to read with dark.
I don't know, that red on black.
Yeah, yeah, yeah.
You could probably change that with a little CSS action.
Probably, yeah.
Anyway, those are my extras.
How about you?
Oh, yeah, very nice.
I got a few.
Just following up on your extra real quick, I'm doing a Stories from Python history, like through the years panel, and Barry Warshaw is going to be on there, on the 6th, which is what, four days, Thursday, something like that.
Okay.
Yeah, that PEP story.
I want to try to get him to talk about that.
So my extras.
This one is certainly could be a full-fledged item, but I don't have enough experience.
I don't really know.
But here's the deal.
So you could have some kind of SaaS bug system.
Could be Jira.
Everyone loves Jira.
Or it could be GitHub issues or it could be something else.
But what if you just want something low-key, you know it's going to be right there with your projects, Git is already distributed, So there's this thing called GitBug.
And the idea is this is a distributed offline-first standalone issue management tool that embeds issues, comments, and more as objects into side your Git repository.
So when you
Git clone, you just get the issues.
And when you Git pull, you update your issues.
Oh, cool.
Interesting, right?
It comes with some kind of UI.
I haven't played with it that much.
A CLI, TUI, or even a web browser that you can run based on this.
So that's pretty neat.
And then there's something about it will sync back and forth with things like GitHub issues and so on if you want to go GitLab using something called bridges.
I think that's pretty cool, actually.
I don't know how it works, but it's pretty cool.
But I've not used it at all and I have no interest in using it because for me, all my stuff's on GitHub.
I'm just going to use GitHub issues.
It's just fine.
But I can see certain use cases.
This will be pretty neat.
What else have I got?
Follow up from last week.
there's a our face but um this is from neil mitchell remember we talked about pyrefly the new um type linter my pi like thing for from meta
yeah and
i said oh yeah it's kind of like ty or formerly red knot from astral and i said oh but astral has this lsp so we got a nice comment on that show from neil it says hey from the fire pyrefly team here thanks for taking a look at our project we do have an lsp ide first and lsps um are approximately approximately synonyms nowadays and we're exploring whether this can be added to pilance so there's more to pyrefly than i gave them credit for very cool yeah yeah what else oh i
think
that's it
you ready ready for a joke ides and lsps are synonyms i think um the autocomplete feature the features that make IDEs more than just a basic editor.
Okay.
Like go to definition, refactor, find
usages, that
kind.
I think that's what he's saying.
Okay.
Yeah.
I mean, I wouldn't fire up PowerFly just from a command prompt.
I need to edit this email.
Let me fire up an LSP.
Yeah, exactly.
But I think that's what he said.
Like the features of IDEs are basically just back in or front ends to LSPs.
All right.
Are you ready for a joke?
You did
a
nice job full circling your whole experience.
so I'm going to do that as well like with your pytest and so on. So check this out. We're all as programmers aware by now surely that AI tools are good at writing code and it's going to mean some sort of change for us somehow, right? Some of us are worried that you know maybe this might be the end. So the joke is there's two programmers who are super they're like about to be hung in the gallows, right?
It's pretty intense. It says programmers worried about ChatGPT. And then they look over at the other guy. He's also, he says, mathematicians who survived the invention of the calculator.
Looks like it's the first time, eh?
It's pretty good, right?
Yeah, it's pretty good.
I wonder if that image was made with ChatGPT.
That would be sweet sauce on it.
Probably not, but it's probably from a movie I haven't seen.
Yeah, probably.
First time?
Mathematicians who survived.
Yeah, gosh.
I'm going to show my age, but I still remember all my math teachers saying, you have to learn how to do this by hand because you're not going to mark around with a calculator every day.
Yeah, you're not going to, are you?
Wait.
Well,
you know, maybe.
Maybe.
Yeah.
Maybe you hold enough to your phone.
Yes, I will.
Yeah.
Or
your watch or whatever.
Yeah, and
my kid's oddly good at putting her phone at anything, like a math problem and getting an answer.
She
uses it
to check her work, which I think is good.
At least that's the claim.
But anyway.
We live in amazing times, but also interesting times as the curse slash quote goes.
Yeah.
I'm going to have to read the comments to figure out what async and banana suits mean.
Oh, yeah, there was a banana suit at one
of the videos on Python.
Yeah, yeah.
You have any out there pointed out that from one of the, pulling out some of the talks, one more talk I thought was interesting was Pablo Galindo, Salgatos, and Yuri Silvanov.
that Silvanov was especially fun talking about async and wearing banana costumes.
What could be better?
Nice.
Yeah.
Well done, guys.
Yeah.
Very nice.
Thanks for being here, Brian.
Thanks everyone for listening.
See you.
Bye.