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