Python 3, an Illustrated Tour Transcripts
Chapter: Asynchronous Programming
Lecture: Painting Code Example
0:00 Here's some example code for painting. I've got a canvas here and I've got a paint method and this is our CPU work here.
0:09 We're just going to say loop over some number here and do a mod operation and check that at zero
0:16 and then when you're done with your painting or your CPU work you're going to make a little instance attribute called start
0:23 and you're going to say I'm going to be done and dry them out after start. So we're going to say two seconds after that we're going to let it dry.
0:31 And then we have another method down below called is dry that just says if the current time is greater than the end, then yeah, we're done.
0:38 Otherwise, we're not done, and I'm going to write a little decorator here, this decorator will wrap a function and just tell how long it takes.
0:46 So I'm not going to really talk about how decorators work per se but just know that it returns a new function called inner
0:54 that's going to call the original function, but it's going to start a timer before it and it's going to print how long it took inside of there,
1:01 just for kick so we can have some timing information. Okay, so on my machine, I've got some code here that I'm going to call
1:09 and I'm going to call paint, a paint function, it's going to create a canvas and then it's going to call paint which is the CPU heavy part.
1:17 And then it's going to do this little loop here where it's going to wait if it's dry and it's going to say if it's not dry sleep for a half second.
1:25 So we could say that this is the IO portion it's waiting for something to happen, but it's not really doing any work.
1:32 And if I run this, and I say I want to do three paintings one naive way to do it is just say run paint and do paint and then paint and then do paint,
1:41 that will make three paintings or three canvases. If I do this in a sequential manner like this, it says that it takes 6.03 seconds to do that.
1:49 So a little bit of overhead for the CPU heavy stuff and then some drying time that we've added in there.
1:55 We can switch this to an asynchronous manner by using this asyncio library. So in order to use this I'm going to change my function
2:02 I'm going to put an async in front of it and the rest of my code looks very similar, I've still got my while loop
2:07 but here I'm going to put an await statement here and I'm going to say await asyncio sleep a half-second rather than time.sleep .5 seconds
2:18 and this is what's called a coroutine. This is an asynchronous coroutine, and it gives us the ability to run code that is interruptible
2:27 that has portions where you wait for something else to happen or you can hand off control for something else to happen.
2:33 So I've got a little function that's going to run this. What we're going to do is we're going to make a loop here.
2:39 We're going to get what we call an event loop and then in this event loop, we're going to call a function called gather.
2:47 This is an asyncio, we're going to gather three instances of this async paint. We're going to get three co-routines
2:54 and it's going to return what's called a future here. And this future is something that it can run and interrupt
2:59 and get some result back at some point in the future when it's done. And then in our loop we just say run until complete future
3:07 and this will run this code, but interestingly enough, when we run this code on my machine this takes two seconds, even though it does three paintings.
3:15 So what it's doing here is it's going to say I'm going to start painting my first guy and then I'm going to check if he's dry,
3:22 if he's not, I'm going to call this await asyncio sleep and when you call await here, that gives it the ability to go off to another coroutine
3:31 and so it starts going on the other work, and then the other work starts a canvas
3:35 and then it jumps into that await, and then says okay I can do other work and so it goes into the third one, and then all of them get painted
3:43 and then they just go into this while loop where it's going to keep calling await every half second and it's going to see if they're done,
3:50 and if they are done that's great, it will take them off if they're not it's going to say, okay, I'm going to go and check the next one
3:55 and so it sort of repeats doing that and it can do that at the same time. So this is an example of asynchronous code,
4:01 the cool thing about this is that it's not written with callbacks. And so if you sort of squint at it and if you got rid of async
4:08 and you got rid of a wait there, it really looks very similar to our prior code
4:13 where we're just saying get a canvas painted and while it's not dry sleep. So that's the benefit of this asynchronous code,
4:19 note that we do have to have an event loop and there's some overhead and construction of that in order to run it
4:25 you have to schedule these coroutines in order to run them.