Async Techniques and Examples in Python Transcripts
Chapter: Built on asyncio
Lecture: Demo: Converting from asyncio to Trio

Login or purchase this course to watch this video and the rest of the course contents.
0:00 So we'll begin this Trio exploration by just duplicating this. So we'll copy and then paste it back here and I'll call it prod_trio.
0:10 So let's go over here and again I told you this is not built on asyncio and actually it's not even compatible with it without
0:15 that bridging library so we're not going to do this. We're not going to do that stuff so let me comment out and we'll delete it in a minute.
0:24 So, instead of having a asyncio queue, we'll have Trio. And notice there's a pycharm warning saying this initializer
0:31 this constructor takes a parameter that we're not passing it and that is the capacity has to be set. The capacity's job is to say
0:39 remember when you tried to put stuff into the queue? Down here, we were seeing await putting items into the queue.
0:45 Well, how do you know when it's just going to put something in a queue versus we want this to stop filling up the buffer and stop producing items?
0:53 Well, that's what this capacity is. This is how many items can be put into the queue before it blocks when you call put. Let's say 10. Okay?
1:02 And then all of this stuff, we're going to take all of this and we're going to simplify that dramatically.
1:08 So the primary construct that you'll see in Trio is this thing called a nursery. The nursery spawns children tasks and you know, that's the idea there.
1:18 So what we're going to do is we're going to convert main into an async method. It's going to take one more adjustment
1:23 for this to actually work, below but we're going to convert that to an async method and we're going to say async with trio.open_nursery() as nursery:
1:34 And then recall we want to run that twice and then produce so what do we do? We say, first, we spell nursery correctly
1:42 and then we say nursery.start_soon(). Now it doesn't give you auto-complete which is kind of annoying. So we could do, just do this real quick.
1:52 Complete. We could import this and then start_soon start, start_soon, cancellation scopes, all sorts of stuff.
2:01 So, we'll go in there and what goes in here and we pass a function and then a *args and a name as a keyword argument if we want.
2:08 So and that's pretty cool. We're going to pass this and just the name. There's the function. And then we pass argument one, argument two
2:15 and then if we want we can have the name for debugging purposes, Producer 1. We're going to have another one, do it again.
2:23 And then we're going to have this processor this consumer, and this is 40. There we go! Well, now what else do we have to do? That's it!
2:35 We're actually done. So here's how it works, and let me get rid of this 'cause this is just so you could sort of see the auto-complete list.
2:40 What we do is we open a nursery within an async with block, so this awaits here. And then we kick off all of these tasks. So start_soon queues them up
2:51 and internally these could themselves write code like this that would open child nurseries and they would also basically become child tasks
3:01 or we could pass the nursery and those could also spawn more that are sort of independent of these and so on.
3:07 So we're going to kick all of this work off and then this with block will not be exited. We won't get past line 18 here
3:15 until either it all completes successfully which will be probably the best case or one of them gets an error in which case any still running ones
3:24 get canceled and then we exit the nursery. Or we can do timeouts which we'll talk about later. All right so, this looks a lot simpler, right?
3:32 Don't have to do this, all these weird hoops we're jumping through, we don't have to do that. Now, again, we converted from a asyncio queue
3:39 to a Trio queue, so we got to do that down here. And we don't asyncio.sleep, we trio.sleep. But other than that, pretty much all the same.
3:52 Don't need that, okay. Let's run it and see what happens. Oh, yeah, did I tell you there's one more thing to do? RuntimeError. What does it say?
3:59 Main was never awaited and we exited right away. So down here in order to run this coroutine which is now it is a coroutine
4:07 we just need it to say trio.run in a synchronous context like this. Now our app can run. So it should operate pretty much the same as it was before.
4:15 Well, in fact, basically exactly the same as the asyncio edition. And there it is! Pretty much exactly the way the asyncio edition ran.
4:25 There's a few things that are simpler. Up here we're not really taking full advantage of Trio because of all of the networking capabilities
4:32 that it has for like writing our own server and stuff like that. But, you could check out the docs. They have a cool, like, network TCP echo server
4:40 if you want to see how that's done. This is pretty simple. I'm not sure it's simple enough to justify switching from asyncio to Trio.
4:48 But, I'll show you some more features of Trio that make it really powerful. Maybe do make that switch worthwhile.


Talk Python's Mastodon Michael Kennedy's Mastodon