#100DaysOfWeb in Python Transcripts
Chapter: Days 21-24: Async Flask APIs with Quart
Lecture: Synchronous execution demo
0:00 All right, enough talk, let's write some code. So over here in our demo repository we can see the days, and this is the quart-async section.
0:10 So what we're going to do is we're going to create a simple project that we can work with and we're going to write some regular synchronous code
0:17 and then we're going to convert to async and see how things get better. All, right so first, let me just make a folder here.
0:26 And I'll just call this Python_async. Now this part's not technically necessary but I do want to use one external package
0:33 and because of that, I'm going to create a virtual environment that we can use here. So we're just going to use Python3
0:49 to create a virtual environment. And then I want to go and open this in PyCharm. Use whatever editor you want, I'm going to use PyCharm.
0:59 All right, with that open, let's create a file that we're going to run. We're going to have a synchronous version and a asynchronous version.
1:10 I'll just call that synch_program not super exciting, but here we go. Now, for this one, I'm going to start with some code
1:15 that I'm going to paste in here and we're just going to talk through it because it's a synchronous program, you guys
1:21 already know how to write this stuff. I want to have a really clear foundation to make an asynchronous version
1:26 but it'll still be interesting to explore. Okay, so you can see I've pasted some code here
1:31 and we're going to use this external package called Colorama. So I'm going to create a requirements file
1:37 just so you can clearly see that you need to have this. We'll come down here, pip install -r requirements.txt
1:48 into our virtual environment that we created. All right, everything is looking good. Now, let's talk about our program here.
1:55 So we have this main method. And the main method is going to do sort of this orchestration thing. So it's going to print out that it's started
2:04 and we're using Colorama to make sure that is white. And I'm also flushing it so that you immediately see the output, we're flushing everything
2:11 so that you immediately see the output. This is important because the interweaving of behaviors from the different parts of our program
2:17 are really important to detect. Okay, so what we're going to do is, we're going to implement this pattern called the producer-consumer pattern.
2:25 Now, the idea is that there's some part of our system, maybe it's even a web service that's receiving an external request.
2:30 It's going to generate stuff to be processed and basically put into a queue or a list this data thing here, in this case.
2:39 And then another part, once the data's been generated is going to take that data and process it. So if we look down here, you can see
2:47 here's the generated data and it's super basic it just goes and creates a square of a bunch of numbers and throws them into this list.
2:52 And it prints out yellow, the generator is yellow. And then the processing part says we're going to go down here and loop over this
3:00 and pull this data out. And in cyan, a blueish, it's going to say we processed this value. It also computes how long from a request to generate
3:11 or the generation of data to the actual processing of data this takes. Let's go over here and run this in PyCharm. You can see the app has started
3:26 the white's kind of gray in this little terminal thing, but it's okay. Then we're generating items notice all of the work is being generated
3:32 all the generation is happening, and then the processing. That's not surprising, we call generate_data
3:39 and then we call process_data, totally reasonable. So we're going to do 20 items, and now they're processing
3:45 one, four, nine, these are the order they came in. And notice, the first one took almost 20 seconds until it got to be processed.
3:52 And if you go down, it gets a little bit less drawn out. But the generation takes some time the processing takes some time.
3:59 So you can see the best case scenario the one that was closest, because processing is slightly quicker than generating
4:05 it still took 10 seconds to get to that request. And notice, it all happened, all the generation, all the processing. Let's just look really quickly
4:16 at what we're calling it up at the top that's totally reasonable, right? We called generate_data 20 times
4:20 and we did 20, and then we called process_data and we processed 20 at a time. But if we look at either of these there's a part where we're waiting.
4:30 And this simulates requests coming in or we're waiting on an external system without adding the complexity of something like that
4:36 which we could build, but would be way overkill in terms of trying to demonstrate this. This is just simulating, it takes some time
4:45 to do some work and that time probably depends on an external system, right? We're waiting on something, right?
4:50 Waiting on a database, waiting on a web service. We're not really doing that so we're just calling, time.sleep which puts our thread to sleep.
4:58 But it means that it takes half a second at least half a second, up to 1.5 seconds to generate an item. Same thing, we're processing the data
5:08 we're pulling out just basically holding onto it and talking about processing it and then it takes us half a second to process it.
5:17 Okay, so this is this program. This is the synchronous version of what we're doing. And we've introduced via time these
5:24 sort of arbitrary wait periods, but they're very much modeling real world things like databases and web services and so on. How can we fix this?
5:33 How can we make this better with asynchronous programming? Well, if we could say, after we've generated a few items
5:40 while we're not generating, we're just waiting maybe the processing could kick in and process the few we've already generated.
5:47 But if we're not processing any because we're waiting down here, we could generate some more. These could work as a team, but they don't.
5:54 They don't because we wrote this very straightforward program. Grab the time, print out some colored stuff but really that's not so interesting.
6:02 This, this is all there is to it. We said, generate_data, and then process_data. So we're going to generate it and wait, and then process it.
6:11 And that's the way synchronous works. But we can do better if we write a different version.