If you're a fan of Python's async and await keywords and the powers they unlock,
then this episode is for you. We have Timo Furrer here to share a whole bunch of async
IO related Python packages. Timo runs the awesome asyncio list and he and I picked
out some of our favorites to share with you. This is Talk Python episode 389 recorded November 3rd,
2022.
Welcome to Talk Python To Me, a weekly podcast on Python. This is your host, Michael Kennedy.
Follow me on Mastodon where I'm @mkennedy and follow the podcast using @talkpython,
both on fosstodon.org. Be careful with impersonating accounts on other instances. There are many.
Keep up with the show and listen to over seven years of past episodes at talkpython.fm.
We've started streaming most of our episodes live on YouTube. Subscribe to our YouTube channel over
at talkpython.fm/youtube to get notified about upcoming shows and be part of that episode.
This episode is sponsored by Microsoft for Startups Founders Hub. Check them out at
Talk Python.fm slash Founders Hub to get early support for your startup. And it's brought to you by
Sentry. Don't let those errors go unnoticed. Use Sentry. Get started at talkpython.fm/sentry.
Transcripts for this episode are sponsored by Assembly AI, the API platform for state-of-the-art
AI models that automatically transcribe and understand audio data at a large scale. To learn more,
visit talkpython.fm/assemblyai. Hey, Timo.
Hello, Michael.
Hey, it's great to be here with you. I'm super excited to talk about Async Python.
Yeah, same. Good to be here. You know, we've spoken a little bit through GitHub. I think it's
odd, but also kind of awesome how many connections are made through places like that, right? Like,
we've never met in person, but we previously chatted about some Async things on GitHub.
Yeah, it's always nice to kind of see the same people again, which you met like online,
in a call or something, talk about something. It's pretty cool.
And that's why I really enjoy going to conferences because you're like, oh yeah,
you're the person I've been talking to for six months now.
Absolutely.
Yeah. Cool. Well, I'm super excited to talk about all the awesome Async Python things that you've
curated. Before that though, let's just get into your background. What's your story? How'd you get
into programming in Python?
Yeah. So I started programming, I think when I was around 10 years old, I, at the time I was
exploring at an offline computer from my parents, which didn't have a lot of like things on it,
but there were a few applications. And one of those were, I think it's called front page,
like Microsoft front page and publisher, which is like,
Yes. It was like Microsoft Word for creating websites. It was insane.
Yeah, exactly. So I was like playing around with this and just, you know, exploring whatever was
there because I didn't have any internet. And yeah, that's how I got interested in like how things are
built in a computer. And at some point I got internet, I kind of browsed around to see like how
these websites really work like. And yeah, that's how I got into PHP and HTML and did some website stuff.
Couldn't you open a website in front page? Couldn't you like point it at a URL and say,
open this and it would pull down the HTML, like into the editor? I think I remember.
I don't really remember.
What a weird piece of software that was. Sorry, I don't need to do it. I'm just thinking back of like
the early web was a weird time.
I more use publisher than I use front page because it was more complex for me at the time. And I didn't
really have any documentation or tutorials. So I, yeah, it was more like fiddling around and
getting something to work and something to happen.
Cool. So you found your way to PHP.
Yeah. Then I went to PHP, did some very basic websites,
like guest books and these kinds of things with PHP, but nothing, nothing really big.
And then after mandatory school years here in Switzerland, I started an apprenticeship
at Roche. It's a pharmaceutical company. So if you, if you've done any PCR tests lately,
you probably have done that on an instrument of them. And there I was in a team where we did
hardware simulation testing for software, which is running on these instruments. And all these,
like the testing framework around the simulation was in Python. And that's basically how I,
I would start in Python. Yes. It's mostly like testing code and providing frameworks in Python
for testing.
That's cool. That's a neat way where you can connect your code to physical things,
you know, testing.
Yeah. It's super nice. Like lab equipment and stuff. The simulation at the time, it also had
some 3D visualization. So you could see motors moving around and kind of, you know, see pipelines
colliding and these kinds of things, which was pretty awesome for me at the time because it was my first
job basically. And yeah, it was super cool. It was super cool. We also built with Python,
like a distributed testing framework or testing system, kind of like you would have in Jenkins
these days or, or any other CI system.
Yeah. They probably don't have as easy integration to actual hardware.
Now, when I pushed to this branch, I wanted to fire up that robot. Oh, okay.
Exactly. And also like a huge problem is like error case testing. Like you can't just break a needle
in an instrument while, when you're running something, because either you get hurt or it just costs you a
thousand dollars just for breaking something for testing. So you need some kind of simulation to
actually do that.
Yeah. Very fun. How about now? What are you up to now?
Yeah. I started a new job at GitLab. I'm a senior backend engineer in the
configure group. And what we're doing is we provide Kubernetes integration for GitLab, GitLab projects
and groups, these kinds of things, and also are responsible for the infrastructure as code features
like the Terraform estate backend and the Terraform provider, which also I've been
maintaining for a year now. That's just like an outside contributor. Yeah. But this is mostly go.
If maybe, you know, Ruby is a big player in GitLab. So the entire GitLab rep was mainly a Ruby and
Rails application.
Give us the elevator pitch on GitLab. Is it, I should use GitLab instead of GitHub or something else?
Or what, what's the value proposition for GitLab?
It's a good question. What do you see here also on the screen is that it's called the
one DevOps platform. So it provides much more feature, I think, than, than GitHub in terms of like front planning
to production, then monitoring an application, get like all these insights, which you cannot really do on GitHub.
So you have all, yep. You basically have features for all the DevOps lifecycle stages.
And here, for example, you see the very Fiverr. You have a very powerful pipeline integration.
The open source world is happening on GitHub, but a lot of enterprises are using GitLab these days for
developing their applications.
Yeah. It's definitely an important piece of, piece of the puzzle out there. And how long have you been
at GitLab?
Just one month. Actually, today marks my one month being at GitLab.
Wow. So you're probably, yeah, you're probably just starting to get comfortable with like how stuff
works and how you deploy things and so on.
Exactly. It was a lot of onboarding, but I've been contributing before.
So not everything was new enough in using GitLab as a user. So it wasn't that hard, I would say.
Cool. All right. Well, let's go ahead and jump into your project.
Sure.
It's one of these awesome lists, and it's about one of my favorite aspects of Python because it
async.io, async and await, they let you write such neat software that really takes advantage of
latency. And when other parts of the system are busy, you can just keep on going without
rethinking how your code works all that much. So I'm a super fan of async and await and Python and all the
languages that use it, I suppose, because I just like the idea. But, you know, tell us about your project
and maybe first start with like, what the heck is an awesome list anyway?
An awesome list is just a curated list of projects or whatever the awesome list is about. It could be
recipes or whatever. And it's just trying to collect awesome pieces of that thing. In this case,
async.io, which are async.io packages or projects, and you basically showcase them to the readers and
they could, you know, take inspiration for the next project stack or can just explore like what's out
there and what people feel that is awesome. And yeah, I mean, I'm not an expert in all of these by far.
So I'm more like librarian off the list and rely on people contributing actually their awesome
projects or ideas or whatever.
Yeah, neither, just as a disclaimer, a front, neither of us are, you know, maintainers of all these
projects or like we're not super experts. It's more of a survey of all the cool things. And I do think
that's one of the really cool powers of the awesome list. You know, I remember the first time I found
awesome Python. I was like, wow, look at all these things I didn't even know existed, right? It's,
it's not necessarily that you use the awesome list to make a decision about what you use,
but it, it's like a good starting point for research, depending on whatever area,
like you've broken your list into stuff about databases and about networking and about web
frameworks. And as we'll see, and you know, you go to that section you're interested in,
you're like, oh, here's my 10 research projects to figure out what I want to do.
I think it's also nice to just, you know, once in a while browse through it and see like where,
where the ecosystem is at and like what new things have been popping up. So.
So another thing I think maybe is worth touching on, I get the sense, although I'm not a hundred
percent sure, cause I'm asking you now that these things that get put there, they don't,
it's not an exhaustive list. It's more of a things that the community thinks reaches some threshold for
interestingness. So under the PRs, I see you got a new one an hour ago.
Yeah. So under the PRs that you have a please vote before these are accepted because like what
it means to accept a PR is really to add a line to a read me. It's not like a super,
oh boy, how does this affect our overall performance? Like there's not a lot of considerations in that
regard, but the question is sort of, let's talk about whether it belongs on the list, right?
How do things make it on your list?
It's a very good question. And I never been really strict about these rules and maybe I should be,
I don't know, but I usually put this please vote label on pull requests just to see if people are
interested in this. Usually I also check things like the stars. When was the last contribution?
Like how many, how many contributors are there? Because if we put something here on the list and
then people start using it and we burn out some maintainers of a library, we just wanted to do,
you know, publish something. Yeah. I don't know if that would be a good idea, right?
Right. And on the other end of the spectrum, you've got, you know, maybe there are people
who publish something just for the heck of it, but there's one person they've touched it two years
ago and you know, it's, it's not necessarily something you want to recommend if there's five
stars and no one using it. And is it really going to be good enough? Okay, cool. So I'm guessing it's
open for people to go and do more PRs and suggest more things if they listen to the show and they're
like, but you forgot about this awesome thing.
Yeah. If people are listening and have something awesome, please create a pull request. Always great to
have some addition. Yeah. Cool. All right. Well, let's, let's go through it. So I think we'll just
take it section by section or topic by topic. And I know you pulled out a couple of things that are
interesting to you. I grabbed a couple as well and we'll just, just touch on them, you know,
kind of work on that awareness and cover the broad spectrum of what's available. So we'll take it,
I guess the top section that you have here, probably the most important section I would say
is web frameworks, right? There's some interesting ones. First of all, it's kind of notable. The
ones that are not there yet, maybe actually, maybe there's some PRs that should be making their way
there. The really traditional web frameworks that people think about are not there, right? We don't
see Flask directly, although through court it's there, which is kind of its full async implementation.
Django is not listed. Bottle, Pyramid, bunch of these older ones, but the really hot new ones are here,
right? Like we've got FastAPI and Sanic and some of the others as well.
I guess people are just probably more excited about those and then, you know, they're kind of hyped
and at those and that's probably why they end up here and not having like Pyramid or the older ones.
Yeah. Well, Pyramid doesn't have an async version, but you know, it's interesting that Django does.
And I think maybe somebody should do a PR for Django now that it actually properly supports all the way
to the database layer. But, you know, until recently it didn't. And what's notable,
I think about all of these frameworks that are here on the web one and pretty much for many of the
others as well, is not just they have a capability to do async, but they were kind of born to be async,
right?
Yeah, you're right. And I think also some of them, I mean, they're all, they're not all on the same
level, I would say. Like we have Starlet, which may be like a very lightweight framework that others
kind of build on top, like FastAPI, which, you know, Starlette may be more comparable to Quartz
than Quartz is to FastAPI, right? So you have these kind of different layers where people could build
upon and, you know, so it's some variety there.
Yeah. And you've got a couple of WebSocket style ones in here as well. They're maybe not full frameworks,
but they work in that regard. Yeah. So, you know, notable to me here, certainly, I mean,
FastAPI is definitely taking the world by storm. It only came out a couple of years ago and it's
already got 50,000 GitHub stars and that's close to what Flask and Django have. It's certainly a popular
one. Yeah. Have you got any chance to play with FastAPI?
I do. Yeah. Or I did. At my last job, we built some applications on top of FastAPI. And we also,
at Roche, we opened source one, which is kind of nice. I always liked the, like the FastAPI experience
overall. Like, you know, the documentation is super nice. I think Sebastian did a great job in also
taking the extra mile to explain more general concepts than FastAPI, like introduction to AsyncIO
and these kinds of things, which the others do not have. They don't need to, but it's just that you
can see that they really care about the community and the users of FastAPI to make it very easy to
put something into production. It definitely stands out in that regard, for sure. So FastAPI is notable.
I also think another one worth giving a shout out to is Starlit. Now, Starlit is not as popular,
right? Having 7,000 GitHub stars. Not that this is like a popularity contest, but it gives you a sense of
like how many people are using it, right? And so Starlit is its own web framework, but it is also
something that can be used for the building blocks of other web frameworks, which I think is unusual
for, you know, Flask isn't like, well, take us apart and just use us. Don't actually use Flask or,
you know, but FastAPI itself actually is built on Starlit. So much of what people love about FastAPI,
they actually love it about Starlit. It's just kind of like a pass-through.
Yeah, I think for a lot of things, FastAPI is just a pass-through to Starlit. And that's what I
meant before with a lot of people are like comparing RCD block posts like FastAPI versus
Flask or Quart and these kinds of things. But it's an unfair comparison because they're like Starlit and Quart,
I think they're meant to be extended into something like going from the microframe or to your,
like that application afterwards. And I think you will have, and they'll start using FastAPI if you
need all of these features. Then, you know, it depends on the use case, I guess.
Very cool to learn about that one. Also, Sanic. I hadn't really been tracking Sanic until recent.
I had been and then kind of didn't pay too much attention. But this is a pretty popular framework,
16,000 stars. And yeah, it's kind of got its own philosophy. It's a little bit like Starlit,
actually, in its style.
I've never used it. I've seen it around, but I never really looked into it. So what is it that
it has a different style? What do you mean?
Well, so many of the web frameworks, that's a great question. So many of the web frameworks
these days are like, we're a brand new web framework. We look just like Flask, except,
you know, we're just like Flask, but we're API oriented and we come with auto documentation.
We're just like Flask, but we do this other slightly different thing. You know, they're,
they're all like, you create an app and then you say app.get or app.route on your,
and you kind of build up out of a blueprint or API router style of like separator, right?
This, there's so many of these new web frameworks that are highly inspired by Flask,
but they don't carry over the same runtime. They carry over kind of the shell API concepts,
right? And Sanic is not so much like that. So if you go and check out Sanic, they have like a good
getting started. Let's see if I can pull up an example. They have a huge button that says,
get started. Maybe I should click that. So if you look at the way that, that it works is you just
create functions. Here's, they're using this app.get. So I saw some, I believe that were,
you just say, here's a function, here's its URL, go and call it, right? Where it's a little more
assemble it back together. But yeah, anyway, it's, it's an interesting web framework as well,
a little bit different. And it's, I think it's really nice that there's all these
people attempting different perspectives on solving the same problem.
It's cool. And it probably depending on the use case, one suits you better than the other. I mean,
it's not that FastAPI just because it had so many stars that it's always the best choice,
right? Maybe Quark is better for your use case because you want something very minimalistic or
something you can extend in your own ways.
Yeah. And some of these like Sanic just added this ability to have background workers that are managed.
So you don't have to go all the way to like a salary worker type of infrastructure, just the web
framework will manage it. And I believe Starlette also has that. Yeah. I guess one more thing to give a
shout out to is the stuff from the Encode folks. There's a lot of those appearing here. So they've got
Starlet, they've got HTTPX and UVicorn, right? Once you get one of these frameworks, you got to run it,
right? Yeah. And probably it's one of the most popular for production, I think.
At least that's what we've been using and we've been super happy. I mean, yeah. Word's great.
In fact, if you use it with UV loop. Yeah. UV loop will make an appearance a little bit later
as well. But yeah, I've been using UVicorn for production also. I'm loving it. Okay. And I guess
also one thing I'll put into the show notes here is I can't remember which framework had this that I
pulled it up. It might've been Sanic or Starlet, one of those two, but they created a filter across
the tech and power web framework benchmarks that just highlight the Python ones, right? Cause there's
how many, 290 frameworks in this. I don't really care what this obscure rust, super lightweight thing
does because it's not a full web framework and I will never use it and so on. So it's kind of
interesting to compare just the like raw basic ones or whatever. But if people are,
doesn't necessarily matter too much, but if you kind of want to get a sense of what performance
looks like across all of these, you know, here's a, I'll put a link to the tech and power benchmarks.
I don't know. What do you think about these things? Does this influence you to see, oh,
Sanic is above FastAPI or do you not care?
It's nice to see those comparison and kind of see how the theory optimization in these
frameworks can translate to, to practice. But in the real world, I would say that it doesn't
really matter too much because it's probably your business logic, which is slowing you down.
Yes.
And these kinds of things or latency to your database or whatever, and not the framework itself. So
I would take those with a grain of salt.
Yeah. It's kind of like asking, well, if I have a tight loop and I increment a number,
how fast can I do that? Like, okay, well, sure. C++ is super fast for that, but that's not what
real software does. Real software interacts with all these things. And like that difference you
think is so huge is like a little marginal bit over the real work.
This portion of Talk Python to Me is brought to you by Microsoft for Startups Founders Hub.
Starting a business is hard. By some estimates, over 90% of startups will go out of business in
just their first year. With that in mind, Microsoft for Startups set out to understand what startups
need to be successful and to create a digital platform to help them overcome those challenges.
Microsoft for Startups Founders Hub was born. Founders Hub provides all founders at any stage
with free resources to solve their startup challenges. The platform provides technology benefits,
access to expert guidance and skilled resources, mentorship and networking connections, and much
more. Unlike others in the industry, Microsoft for Startups Founders Hub doesn't require startups to be
investor backed or third party validated to participate. Founders Hub is truly open to all.
So what do you get if you join them? You speed up your development with free access to GitHub and
Microsoft cloud computing resources and the ability to unlock more credits over time. To help your startup
innovate, Founders Hub is partnering with innovative companies like OpenAI, a global leader in AI research
and development to provide exclusive benefits and discounts. Through Microsoft for Startups Founders Hub,
becoming a founder is no longer about who you know. You'll have access to their mentorship network,
giving you a pool of hundreds of mentors across a range of disciplines and areas like idea validation,
fundraising, management and coaching, sales and marketing, as well as specific technical stress
points. You'll be able to book a one-on-one meeting with the mentors, many of whom are former founders
themselves. Make your idea a reality today with the critical support you'll get from Founders Hub.
To join the program, just visit talkpython.fm/foundershub, all one word,
No links in your show notes. Thank you to Microsoft for supporting the show.
Yeah. And I would also say that most of the people don't actually need that speed. If you may need it, you may also choose another language or, you know, if this really is a thing for you, then yeah, I don't know if this micro optimizations between Sanic and FastAPI really brings you much benefit.
I would certainly say pick the API that makes you happy.
Exactly.
The programming API and the framework that makes you happy and just go with that. Yeah. Good advice. All right, let's see. Are we on to our next section? We are message queues.
Yeah, I haven't been a big user of any of these. I've been using the MQP one a while ago, so I don't really know where it's at these days.
Message queues are interesting. They're a way to add crazy scalability. If you've got a lot of stuff that takes a while, but you don't need the answer right away. They're pretty interesting, but I just haven't needed them much myself either.
I did not too long ago speak with Min Reagan Kelly about zero MQ and Python, and apparently they're doing a lot of cool stuff for powering Jupyter with zero MQ.
It's way more interesting than I initially kind of in my mind gave it credit for. But yeah, it's a cool project.
So they're hosting Jupyter or what do they do?
They're using for something for like the client server communication. I thought that it's been, that's what I think I remember, but it's been like quite a long while since I talked to them about it. But yeah, we've got the AMQP one. That's the one you talked about, right?
Yes. It's the one you would use if you use rapid MQ, for example. Right. You started using the AMQP protocol and then that's where you can use this library in particular. Right. You have the PI ZMQ. That's the zero MQ one I was talking about. And then some others, one for like Apache Kafka, for example.
But again, anytime you're talking, these are usually separate processes, sometimes on separate machines. You're doing network comms. Like if you, if you have the word I'm talking over a network, then async and await. I mean, asyncio, like what does the IO stand for? Right.
And then I think point being also here is that you have asyncio libraries for pretty much all message queues out there these days. I mean, we, every time I looked and looked for a library, it was, so something was out there and you could use.
All right. Let's move on to the next one, which is the database stuff. So I think this is another area where you spend, you're, especially in the web apps, you're spending a lot of time waiting. So thinking about your asynchronous database driver is super important, right?
Yeah, absolutely. And I think it's not too long ago when there wasn't really good support for asyncio and databases. It's great to see that a lot of projects are now supporting it. And also you mentioned Django, which has it all the way to the, I'm not a Django user, so I don't really know. I also guess that's a huge deal.
Yeah. I mean, that was the main blocker, I believe is the Django ORM didn't have an async interface. And I think it was 4.1, again, not doing a ton of Django myself either, but I think Django 4.1, which just came out.
It kind of completed the whole cycle and added that.
Very cool.
Yeah. So what database drivers stand out on this list for you?
Well, I think asyncpgA is a very popular one if you use Postgres. I've been using it and usually you don't really see much about them actually, because you may use SQLAlchemy on top of these drivers.
Right.
So as an end user, you may not have seen them, but you may have used them.
The only way you might see them is you put the async connection string into SQLAlchemy and it complains that it doesn't have this package. Like, well, I guess I got to install that. Here we go. Right.
Exactly.
Yeah. Yeah. So certainly the asyncpg one, I think is pretty interesting. This one is from the EdgeDB folks, right? From, is that Magic, I believe? Yeah. Magic Stack, like Yuri and crew over there.
So the same people that do UV loop, right? He did a lot of the original asyncio work in Python itself, I believe.
Yeah. I think there's also a nice, interesting Talk Python to Me episode about with Yuri, I think.
It was some.
Yeah. I think I spoke to him in the, about a year ago as well. And that was a great chat. Yeah. Let's see what else stands out to me here. So motor, if you're doing MongoDB, then motor is often the building block, much like asyncpg would be the building block for SQLAlchemy's async.
The motor is the building block for a lot of the Python MongoDB async libraries.
Yeah. I also noticed that for Redis.
Which one is that?
The Redis Pi.
Yeah, exactly. So I noticed a week ago or something that these IO Redis was included into the official Redis Pi library. I don't know when that happened. May have been a while ago, but I still think it's nice to have another separate package, but like the same package you have the sync API for.
And you can kind of use similar APIs so that you don't have to like rethink everything. If you want to switch to async, it just makes it easier to migrate if you want to also move back for some reason.
I agree. Some of these have both APIs, like for example, SQLAlchemy, you can create an async setup connection string engine sequence, or you can do a synchronous one. And depending on what you're doing, you might like this utility doesn't want to be async.
So we're just going to go and use the sync API, but your web app or API might want the async version. Let's see a couple more notables here. The Piccolo one, I think is pretty interesting because I really think the query syntax for this one is quite expressive.
Have you played with Piccolo? I have not, but I still admire its query style.
I recently checked it out though. And I also have the same impression that the query syntax is super nice because compared to others like Prisma, I also looked at lately and while they have type safety with like type sticks, you know, here you actually have the Python symbols or variables you can use, which is, I think, a little bit nicer than having strings, even though they can't be all the completed.
Yeah. And you get, and when you do refactoring, like it understands what's going on. So for just for people listening, for example, to do a select statement, I would say a weight because it's async band would be the class you say band dot select, then band type dot name, and then where dot where band dot popularity greater than 100.
A lot of these ORMs and ODMs have like janky syntax to push operations into it. So for example, in Mongo Engine, you would say popularity underscore GT equals 100. So popularity greater than 100, but it's, you're saying equals, you don't want equals, you want the greater than symbol, right?
This is like exactly the same meaning in SQL as it is in Python, which I just really like that.
Yeah. And it's also super cool if you're, you know, entering a code base and you see these kind of things, because even if you don't know Piccolo, like he would understand what's going on.
Yeah, exactly.
Which I think is a good aspect of a nice API.
It is. So Brandon out in the audience has a question says, so we can use asyncpg in place of psycopg two? I don't, I haven't done enough with this, but what are your thoughts?
I'm not sure if the latter one really is async.
Yeah, I think the deal is the latter one, psycopg two is not async.
Yeah.
And so that's what say SQLAlchemy would use if you had created a synchronous connection. But if you wanted to do the async version, then you would have to use the asyncpg foundation for it, basically. I think that's my understanding, but I do more MongoDB than Postgres.
I think so too, but I wouldn't really know because I've always or lately been using async only.
So yeah, exactly.
It's not the only thing you would have to change, right? You would also have to adapt your code and put the weights here and there and make your code async.
Like you can't just replace the query string and then expect it to work.
So one other one here that I think is probably noteworthy to put in the database drivers.
And I'd like to hear your thoughts on this as well. Is the AIO SQLite?
Yeah.
On one hand, interesting because SQLite doesn't really do much concurrency. So you're like, well, that's silly. Like, why would I ever want to use AIOs?
You know, like the asyncio with it if it doesn't really do that.
But if you're writing a web API or website or something that uses SQLAlchemy and you want to on dev use SQLite just for like a simple test and you want to use Postgres in production, well, guess what?
Your async code will fail to run on SQLAlchemy unless you have AIO SQLite as the foundation like we just talked about.
So it kind of allows you to still test your code and run it, even though you wouldn't necessarily directly use it.
Yeah. I think we've always been using AIO SQLite for testing purposes.
Super nice because you can use like in-memory databases and don't need to worry about the setup too much.
And it just works basically.
I need to be careful though for a few features.
Yeah.
Because it's not exactly a match, right?
Exactly.
So we had the case where, you know, it didn't, it worked in testing and in CI and then broken production because, yeah, or testing against Postgres.
All right. Let's move on to the networking section.
So what stands out? There's not that many of this one.
This is not overwhelming, like the database thing, right?
Yeah. I think probably a lot of people know is HTTPX, which is a super nice requests-like package for making HTTP calls.
It has a similar ATI and the good thing, or what I really like is that you can use it in sync and async and the API looks pretty much the same.
So if you want to switch from sync to async, I think it's a delight to use it.
You can just say HTTPX.get just like you can with requests, which is great.
And then if you want the async version, do they have an async example?
It's super easy to quick.
I think you just create like an async client and then call the same functions on it.
Yes.
That's cool.
Much like requests where you create like a client, you just say, or a client session, I guess it's called.
You say create an async client, then you await the client.get.
Yeah.
It's always interesting to me how libraries decide to add on async and, and I mean, we phrase that, a synchronous and a non-synchronous.
Synchronous version, like the both variants into the same library, right?
Mm-hmm.
Do you see people doing that successfully?
Like, do you see any patterns that you really like when they do that?
I think I actually like how HTTPX is implemented in those regards.
I didn't think much in the code base, but like you have the same like protocols for the, for the API so that you can reuse them easily.
And then you kind of interchanged it.
I think the transport layer in this case.
Yeah.
It's super nice.
But for my own libraries, it always bothered me to, that there is no really nice API to provide both in like the same function.
Like you couldn't reuse the function name in an async version or the method name, right?
You need to have another class.
But I guess that's just how it is.
You know, I think a lot of these probably grow up.
They come into existence to be one or the other.
And then they're like, all right, well, we kind of want to have both.
So how do we add it?
And if personally, if I was going to start from the very beginning, I would like to see what they're doing just for the synchronous version of HTTPX, where you just say HTTPX.get.
Instead of saying import HTTPX, you'd have to say from like HTTPX synchronous import HTTPX or from HTTPX async import HTTPX.
And then it's just exactly the same API, but you have to await everything versus not await.
I don't know.
I think there's like if you said we'll control it at the import level and then what you get is either all awaitable or it's all blocking.
It would be a nice pattern.
Yeah.
By the way, could you await this get?
Not really.
Or is there like a, you always need a client that you want to have async support?
I'm pretty sure for HTTPX, you have to create the client and then you have to create an async client.
Then you can await it.
I've also seen other APIs.
You have get, then you have like a get underscore async, but I kind of, I kind of don't like that since you could just do one import statement, you know, and fix it.
So I don't know.
It's really, as I'm going through all these, these examples that you've curated, I'm thinking like, okay, some of these have both APIs.
Like, how are they making that clear to people?
Right.
What else is noteworthy on that list?
I think maybe we could just super quick touch on it.
You've got an async SSH library.
Like literally that's its name.
And a DNS and a ping, right?
I haven't either.
It's nice to have like here at least to have some, well, if you want to do a ping, like it may not be obvious what to use.
So I think it's a good one.
So I think it's a good one or at least people consider it a good one.
So I think it's, it's nice adding those to the list.
So there are a few like niche libraries on the list, which wouldn't make a huge, like they wouldn't get many votes probably if you do this because.
They're not broadly useful.
You're like, oh my goodness, I've been building a DNS system.
I'm so glad I found AIO DNS.
But actually some of the frameworks, like I believe HTTPX uses that under the covers.
Pretty sure.
Something I played with recently was like using AIO DNS under the covers to make its work a little more asynchronous.
Yeah, it will make sense.
Excellent.
All right.
Tell us about the testing story.
I mean, here of the ones we see on the screen, there's IOMOC, there's AsyncTest, pytestAsyncIO, A-Responses and AIO-Responses.
And I've been only using pytestAsyncIO, to be honest.
And it basically gives you the, like a decorator to mark your Asyncpytest or your test as Async so that they run in an event loop.
There is also now a mode you can set in the configuration where you don't need that marker.
So you would, if you have a test, like you would say AsyncTest underscore some underscore AsyncIO code, and then your normal test code.
And you would decorate this function with a pytest mark AsyncIO decorator.
But yeah, it's not, I think, not necessary.
These days you could configure it to have it in auto mode, where it basically just detects always a coroutine.
I'd schedule it on the event loop.
Yeah, and this is not about trying to say, well, I've got a bunch of AsyncTest functions, so let's try to run them all in parallel, like Xtest or Xdist or any of those types of things.
It's just, I have some function I want to call and test its result.
It's Async, so I have to await it.
In order to await it, the test function itself must be Async, and then how do I run it, right?
Like, now what?
I think the other way would be kind of cumbersome to create an event loop every time and then schedule your coroutine in there and pytest AsyncIO, which just does that for you.
Sure, you could do it, but it would make the code not look normal.
It'd be like all these weird things you have to do to like Async to Syncify.
And we'll see some frameworks that might even do something in that regard for you.
But this is really nice.
It just seems like if you're testing code that is Async, clearly this is something like this is what you want.
Also, mocking.
I hadn't really thought about mocking Async methods, but I guess you need some.
I've done this.
I haven't used this IOMock.
So there is, I think even in UnitestMock, there's an AsyncMock class which you can use.
I'm not really sure why you would need this.
This has changed six years ago.
I wonder if the asynchronous mocking capabilities were not in the framework itself when this got created.
And then probably like, you know what, we should just be able to test our own stuff.
So let's fix that.
Yeah, I'm guessing.
Okay, pretty nice.
You mentioned UV loop before in one of the sections.
This is maybe the only section that has a single item in it, but it's a big one.
UV loop, right?
Yes.
For alternate loops.
Yeah, exactly.
So you could use, if you're on AsyncIO, you can just use the one which is in like CPython.
You could just use that.
But there is other implementation like this UV loop, which is based on LiveUV, which is another
events loop in C.
And it just is super fast compared to the built-in implementation.
I think it's for production use cases.
It's so nice because in order to use it, a lot of times if it's just literally installed in
the environment, things will use it.
Like I believe UVicorn will use it if it finds it and some other things.
You don't even have to say, please use it.
It's just like, oh, it's available.
Let's go.
And if for some reason you need to explicitly use it, like in your code, you just say UV
loop.
You say asyncIO.setEventLoopPolicy and you pass over the UV loop policy class.
And now the rest of your program just uses that.
It's really nice.
And don't really know how many other like alternative implementations actually.
Yeah, I don't either.
But it's really nice.
And it basically bundles up, as you said, LiveUV.
They've got some nice performance graphs.
It says UV loop makes asyncIO two to four times faster.
Who wouldn't want your asyncIO code to just go two to four times faster with no effort?
Yeah.
And it's super easy to install and use.
So there's no really downside to that.
Mario has a totally reasonable question.
Why wouldn't UV loop just be the standard ASyncIO implementation then?
What's the catch?
Well, I don't know what the catch is, but I could assume that it's easier to change outside of
the CPython development cycle.
And probably that could be one of the reasons.
I don't know.
I don't agree.
That's a good idea.
Also, you know, do you want Python itself to take on LiveUV?
I'm sorry.
Yeah.
LiveUV as a C dependency.
And then third, when I played with UV loop originally, it's been a few years, it didn't
work at all on Windows.
Like its implementation of LiveUV was a, for whatever reason, it just wouldn't install
on Windows.
And that obviously is a breaking change or a stopper.
So maybe even if it works on Windows, maybe there's like some obscure place where Python
runs, but LiveUV won't, you know, think of like some small device like a Raspberry Pi
or whatever.
I don't know.
Yeah.
And I think we're coming down to the discussion you had before about the benchmarking again,
that maybe not everyone actually wants this feed or needs this feed.
Yeah.
Maybe it's just for like a very optimized production use cases.
And you actually need this four times faster.
And for all the other use cases, maybe it's your code that is slow anyways.
You don't really care too much.
Yeah.
There was a discussion about a few years ago about why is requests not just built into
Python, right?
They're like, well, there's URL stuff in there, but it's way less obvious how to use it compared
to just request.get done and response.json when you get your response back and whatnot.
And they debated that at the core dev summit.
And they decided if we put requests into CPython, kind of like you were saying, is it will,
it'll actually slow the progress and the evolution of requests itself.
And they wanted to keep this nice library, its own thing that could go at its own pace.
This portion of Talk Python To Me is brought to you by Sentry.
How would you like to remove a little stress from your life?
Do you worry that users may be encountering errors, slowdowns, or crashes with your app right
now?
Would you even know it until they sent you that support email?
How much better would it be to have the error or performance details immediately sent to you,
including the call stack and values of local variables and the active user recorded in the
report?
With Sentry, this is not only possible, it's simple.
In fact, we use Sentry on all the Talk Python web properties.
We've actually fixed a bug triggered by a user and had the upgrade ready to roll out as we
got the support email.
That was a great email to write back.
Hey, we already saw your error and have already rolled out the fix.
Imagine their surprise.
Surprise and delight your users.
Create your Sentry account at talkpython.fm/sentry.
And if you sign up with the code talkpython, all one word, it's good for two free months
of Sentry's business plan, which will give you up to 20 times as many monthly events as
well as other features.
Create better software, delight your users, and support the podcast.
Visit talkpython.fm/sentry and use the coupon code talkpython.
Yeah, makes sense.
I think there, I also heard that the security there, it's easier to patch the library in
like on PyPI and make people an update than shipping a hotfix release or whatever of Python
to fix those security issues.
Absolutely.
And Brandon just says, I just learned that FastAPI starlet use UV loop by default.
Yeah, that's what I, that's one of the things I was thinking of.
If it's installed in the virtual environment and it has access to it, it'll just take it and
go.
No need to make any changes there.
All right, awesome.
So that's just one, the one thing in the alternate loop section, but quite, quite neat
indeed.
And then there's got to be a miscellaneous, right?
There's got to be a utils.
There's got to be a helpers.
There's got to be something that's just like, well, what the heck is this?
Tell us about the grab bag at the end here.
Yeah, there's a few here, which I find very interesting.
The first one here is Iocham, which adds a CSV style concurrency feature.
So if you've, if you've done some Go programming, you came across channels, I
would say this IO gen brings these kinds of patterns into Async IO.
So basically what you will have is you can create a channel and then you can have multiple
coroutines like a producer and a consumer listening and writing to this channel and you can have
it buffered or not.
And these kinds of things can select on multiple channels and react on incoming data and these
kinds of things.
So it's just another, other way to communicate between your coroutines than what you would probably do with the built-in
mechanisms.
Sure.
And a lot of those patterns are incredibly hard to get just right with the event signaling and all those things.
Yes.
And so if you can just hook it in, then it's good to go.
You could probably make this work with queues and events.
Yes.
And then all these, but it's nice to have the abstraction.
Yeah.
Of these.
Exactly.
These primitives.
Yeah.
It's sort of equivalent to saying, well, you've got a HTTP server built into Python itself.
Like, why do you need Flask?
No, no, no, no.
No, we don't want to do this.
Other notable ones here, like one that stood out to me is AIO cache, which is pretty straightforward.
It's like just a cache, right?
Add, get, set, even has a cool increment and so on.
But it's Async IO and it talks to Redis, Memcache, Redis and Memcache, MessagePack, a bunch of
different capabilities it has, right?
Yeah.
It looks super cool.
I haven't used it.
But yeah, it's nice that you can just switch out the backends and use something else.
Also, the API looks very straightforward with like just .set, .get.
It's pretty straightforward to, you know, await a cache.get or await a cache.set.
Yeah.
It seems like a real nice, real nice API.
The decorators will look interesting so that you can cache our coroutines, probably.
Yeah, exactly.
That's just, that I didn't really catch that before you.
Right.
So people are probably familiar with the func tools.
LRU cache.
LTS cache.
The LRU cache.
Yes.
I'm like, oh, there's a, it's not a T. LRU cache.
Thank you.
But this is that idea.
But instead of saying, well, where you cache that is in memory, as you just say, cache
equals Redis, which is like, wait a minute.
Okay.
That's cool.
That's really cool.
It's cool.
Just make sure the latency is lower than actually your execution time.
But yeah, it looks very nice.
That's a really good point.
Like if you call this a bunch of times and the Redis is far away, like it actually might
just be slower.
Yeah.
But the CPU will be nice and low.
So you'll be fine.
You'll be fine.
Yes.
This is a cool project.
Another one that I really like, I think adds some important capabilities is AIO files.
Tell us about that one.
Yeah.
It basically provides you, say, file API support like you have with normal, like open
and these kinds of functions and do it async with asyncio.
But I'm not sure if I read it here, but I think on some platforms like Linux, it's hard
to actually implement this correctly with like ePoll and stuff.
I don't know if you know more about this, but I heard it.
It's not really a big benefit actually to run it async.
Yeah.
I don't know either.
What it claims here is it doesn't try to, I don't think it tries to do fancy work with
truly hooking into asynchronous stuff in the file.
So it just says, it's just going to run it on a background thread basically.
Oh yeah.
So it probably creates like a worker thread.
And whenever you ask to read it, just in the back, it goes open.
And then when you say a wait read, it's just on that thread, it maybe sets an event and
then does a read or something.
I don't know, a little bit of like juggling background threads.
But yeah.
So it, in a sense, it may make it actually timely bit slower.
But if you're doing an API and the API has got to read or write a big file, that could be
a problem.
The other one is, you know, we'll see this in a couple of things we're discussing in
this section.
So it's a lot of things that we're talking about.
It could be a lot of things that we're talking about.
user slash whatever.
But it could be backslash backslash network server backslash network drive, right?
It could be very, very slow where all of a sudden, you know, unlocking that, that access
is a huge deal.
Yeah.
Does this actually support us?
Uh, talking network files?
Oh, yeah.
With multiple drive here.
Okay.
Yeah, exactly.
Yeah.
Like what the thing you're talking to might actually be far away, you know?
Yeah, exactly.
It does say handling local disk files, but I bet if you mapped it in your OS, it wouldn't
know, you know?
Yeah, probably would work.
Yeah.
What I also like here, there is also an IO path.
Yes.
Which, that one actually looks maybe even cooler, right?
Yeah.
I think a lot of people are using pathlet these days and IO path basically gives you an async
path type, which you can just wrap around your strings or path objects.
And you get the same methods, but just, you can evade them basically.
So you can, you can have your path.open, path.exist and you have, need to use an upgrade.
This is for you.
I don't know here how it's implemented, if it's also using background threads or if it
doesn't match it.
Does it actually hook into the true IO completion ports and all that kind of business?
Yeah.
So this is really cool.
So you could create, we all know about path from pathlib.
It's super neat.
And you can ask it questions like, does it exist?
Or, you know, create this directory?
Or is it a directory?
Or you can actually say, read bytes, write bytes, read text.
There's a lot of things that you would do with a context manager that become just one-liners
with pathlib.
And this async pathlets, you make all those asynchronous, you're like, await pathlet exists,
await write bytes, and so on.
And the cool thing is there really, I think, try to be a drop-in replacement for pathlib
in the asyncio world.
So if you've been having a code base or have been using pathlib in an async code base, it's
super easy to just switch to an async version of pathlib.
Oh, excellent.
It says the implementation here.
Let's see.
Does it tell us?
It inherits from pure path, which is cool.
So you could use it as an argument to some of these, some of the pieces that will take path
objects directly.
It takes advantage of lib AIO for asyncio on Linux, which is probably where you care
most about performance because that's where your server is, right?
Yeah.
I don't know anything about lib AIO, but that's probably some sort of native type thing going
on there.
Like Linux native asynchronous IO access library.
Yeah, that's okay.
So maybe this is not just a little bit better.
Yeah, maybe it's not just a little bit better than AO files because, well, you can work with
path objects, but it has like an OS level implementation as well.
That's pretty cool.
All right.
I'm using it.
It looks good.
Yeah.
That looks like, those are all the ones that jumped out at me.
Those, those two that you called out there, those cache and the files or the, and the path
history, I guess.
Anything else worth mentioning real quick?
I think so.
I mean, the misc one is just a miscellaneous package in the miscellaneous packages, I would
say.
So yeah, when I saw that, I thought this is probably the longer thing, maybe it's in there.
It's like the meta, meta miscellaneous, it's like the, or miscellaneous squared or something
like that.
That's right.
A bunch of random helper things in there.
That's cool.
Then you have some stuff.
Let me just go real quickly flip through.
Like there's some stuff on writing, like tutorials and articles, and then some video talks about
Async.io in there, right?
I think there are good ones.
I think a lot of them are actually from David Beasley.
I'm not sure.
Yeah.
David Beasley has done some cool stuff with kind of recreating Async.io live in the early
days.
Yeah.
And then Yuri, who we spoke about.
Yeah.
If you really want to know like how you can think about like a mental model of Async.io,
I think these are very good talks.
She's better understand.
Absolutely.
Cool.
I don't know about this guy though.
All right.
The last thing you closed it out with is alternative implementations to Async.io, not just like
a tool you can use within Async.io, but there's Curio and Trio are like probably the big two
there, right?
I think Curio, I think it's from David Beasley as well, but I don't think it's maintained
really, but I think it's been a nice experiment.
And at the time I looked at it, it was kind of minimal in the implementation.
So you could kind of digest and see how something would be done like Async.io.
Okay.
There's Trio, which I think is still out there.
And that's also why any.io exists probably because it kind of, you can use any.io as a
front end for Trio or Async.io and add some more high level features on top of Async.io.
Yeah.
I recently had Alex from Any.io, Creative Any.io on there and just real quick shout out
for some of the things I thought was cool over there is it could run on top of Async.io or
Trio, which is cool.
It also has some really interesting aspects for like converting threads into converting regular
functions into awaitable things by running them on other threads.
And it can either do that on a thread or it can even do that on a sub process.
So you can like go and say await run process and then you get its value back, right?
Or you could do that with sort of multi-processing or even create a asynchronous for loop over
the output stream, like standard out of some process.
I could have used this a few times in the past.
Yes, I know.
Like this is really, really neat to be able to do that.
And the other thing is the synchronization primitives like events and semaphores.
There's, he says, I haven't tried it out really, but they're supposed to be a little bit less
likely to get deadlocks or race conditions because you can't, they're not reentrant basically.
Okay.
Nice.
Yeah.
So there's a cool bunch of cool little helper type things in the IO there.
But well, that's pretty much it.
I think for, for the list, that was a lot, but a lot of good stuff.
A lot of awesome stuff.
Wouldn't you say?
Yeah.
And I'm sure there's more awesome stuff out there.
Like the Esco live one we've covered.
You added one five minutes before the, before the talk.
Because I was going through, because I was going through, I'm like, oh yeah, this one,
like I was looking at motor.
I'm like, oh, well, the stuff built on motor.
There's some good ones there.
Let's throw those in and people can vote for them if they want.
But yeah, there's, I'm sure that people listening, if they maintain one of these libraries
or they're big fans and use one a lot that's not on the list, you know, go make a PR,
right?
Absolutely.
Yeah.
I also plan to add some more automation so that we can, for example, check for dead
links.
It would also be nice to kind of catch outdated libraries, like the, which one, like the IO
mock we've seen before.
Yes, exactly.
Like, you know, if it hasn't been touched in six years, it probably isn't needed anymore,
right?
Could fade.
Exactly.
Awesome.
I mean, this is a great resource and I, I sort of shouted out the popularity of some of
these projects to give us.
And it's like, your list has got 3.7 thousand stars.
Like that's pretty awesome.
That's a lot of people who got value from it.
It is.
And I can only recommend to, to look at these lists, you know, whatever list it is, there,
there are gems in there and it's kind of nice to discover them.
Yeah, absolutely.
Really quick out in the audience.
Mato's logic says starlit, I'm sorry.
Star light is an async framework built on top of star lit and Pydantic, which is a good
candidate.
I didn't actually give a shout out to it, but I thought, oh no, it's not on there.
Okay.
Well, PRs, PRs are accepted and reviewed star light.
There you go.
Cool.
All right.
Timo, this is really excellent project here and a ton of people are getting value from it.
So thanks for putting it together.
Yeah.
Thanks to all the people who, who suggested the awesome stuff.
So I'm, as I said, merely the maintainer of the list.
So keep them coming and we'll make it even better.
Excellent.
All right.
Before we get out of here, final two questions.
I feel like you could just randomly pick one from your list, but the notable PyPI part
project you want to give a shout out to?
I think it's not even on there, but this, it will be tenacity.
Oh yeah.
Tenacity is good.
Yeah.
It's a library for retrying stuff.
I think it has async.
I'm pretty sure it has async.
Okay.
Let's see.
But it makes it super nice if you have like network.
Async retries.
There you go.
Yeah.
So it's, it's even the same decorator, which is cool from an API perspective.
I don't even think you have to import something else, like something differently.
Right.
Because you can actually inspect the function, which is being decorated and you can decide what
to run.
Pretty cool.
I suggest you use it if you, if you want to retry something or have like unstable endpoints
or whatever.
Yeah.
And all the features you need to call it.
This is a great library.
You know, if you were consuming someone else's API and that thing is flaky, you know, what
are you supposed to do?
Right.
You, you've got to call it potentially, but you can't count it always working.
I've run into that problem on a lot of my projects as well.
And I've either done something like tenacity where you just say, retry it with some kind of
exponential back off or I'll go through and cash it in my database and say, I'm going to
try it.
If it fails, I'm going to go get it from the database and go, it might be a little bit stale,
but at least this, you know, if it's something kind of stable, like a currency lookup, like,
okay, an hour ago, the dollar to Swiss francs, the lookup was this.
And it might not be perfect, but it's better than just going 500 server error.
I don't know how many like wire loops I've written in my life to kind of check a timeout
and then retry and sleep and these kind of things.
And it's hard to get this right because, you know, you want to catch termination of the,
of the program and cancel these things.
So it's nice to have a library for all.
Yeah, cool.
And the fact that they support async is like perfectly blends in.
You should add it to the news as well.
Yeah.
Actually it would belong there, wouldn't it now?
All right.
And then the other question is if you're going to write some Python code, what editor are you
using these days?
These days, VS Code.
It's important though that it has been key bindings.
I've been an end user for quite some time.
So I certainly need that.
Yeah.
But VS Code is my editor to go these days.
All right.
Final call to action.
People are interested in your awesome list.
What do you tell them?
Please contribute to your awesome ideas.
Make a PR.
Also, if you have ideas around automation, please send them our way.
Create a pull request or, you know, and achieve your nice.
As a maintainer, that's a very welcome thing, right?
It is.
Find things you don't have to maintain, I'm sure.
Absolutely.
Awesome.
All right.
Well, thanks so much for being here.
Thanks everyone to listen.
Thank you.
Bye.
This has been another episode of Talk Python to Me.
Thank you to our sponsors.
Be sure to check out what they're offering.
It really helps support the show.
Starting a business is hard.
Microsoft for Startups, Founders Hub, provides all founders at any stage with free resources
and connections to solve startup challenges.
Apply for free today at talkpython.fm/founders hub.
Take some stress out of your life.
Get notified immediately about errors and performance issues in your web or mobile applications with
Sentry.
Just visit talkpython.fm/sentry and get started for free.
And be sure to use the promo code talkpython, all one word.
Want to level up your Python?
We have one of the largest catalogs of Python video courses over at Talk Python.
Our content ranges from true beginners to deeply advanced topics like memory and async.
And best of all, there's not a subscription in sight.
Check it out for yourself at training.talkpython.fm.
Be sure to subscribe to the show.
Open your favorite podcast app and search for Python.
We should be right at the top.
You can also find the iTunes feed at /itunes, the Google Play feed at /play,
and the direct RSS feed at /rss on talkpython.fm.
We're live streaming most of our recordings these days.
If you want to be part of the show and have your comments featured on the air,
be sure to subscribe to our YouTube channel at talkpython.fm/youtube.
This is your host, Michael Kennedy.
Thanks so much for listening.
I really appreciate it.
Now get out there and write some Python code.
I'll see you next time.