Async Techniques and Examples in Python Transcripts
Chapter: Threads
Lecture: Cancelling threads with user input

Login or purchase this course to watch this video and the rest of the course contents.
0:00 Let's add one nice little trick or nice little feature to our program here. Notice it's doing all this work, but maybe I'm done
0:11 I've seen enough, we can get out of here. I'd like to somehow cancel. Well, I can somehow, Ctrl + C my way out eventually.
0:21 Well, not really right? Even that doesn't work. Like, that's not the best. You know, Python consists of this little like skull
0:28 cross bones thing, til we're actually finished. That was super annoying. Wouldn't it be nice if there was a better way?
0:34 Well, if we had set these to be daemons at least the keyboard interrupt would've taken it out. But still, maybe we want something a little bit nicer.
0:45 Instead of saying started let's actually use our Colorama here. We can come out here and say something like press enter to cancel
0:56 And you might think, well you can just do input. Like this, with nothing. And technically that will block this, but how do we know.
1:07 We don't have to ask this anymore. You can't just ask have they pressed a key super easily in Python. There are some ways, but it's really sketchy.
1:14 So let me show you one other way that actually is much easier. Instead of doing this, what I'd like to do is somehow
1:22 ask this question, hey are any of these threads done? or rather all of the threads done? And if they are then we're just going to exit
1:30 but if they're not, let's give people a chance to exit. By pressing Enter in the middle in a nice, clean way.
1:39 Okay, so how are we going to go about that? So, this input, like I said there are ways in Python to read whether there's input but it's quite tricky.
1:49 We can just add one more thread and ask that question. You know, what is the input over here? So let's do this.
1:54 We'll create something called the abort_thread. Going to say threading.thread. And it's target, is going to be check_cancel.
2:06 And its daemon mode is going to be True as well. So we need this function and we'll put it below. It's going to be incredibly simple.
2:16 Watch this. check_cancel. Input. Actually let's put this down there. So here, we're going to run a thread
2:24 and that thread is just going to see if you press Enter. If you press Enter, that thread exits. If you don't press Enter, that thread doesn't exit.
2:31 But when we get to the end, because it's a daemon thread it'll be canceled, alright? Here's what we're going to do.
2:37 Going to come over here, and we're going to say while any of these, t.is_alive(). So we can ask the thread, are you alive?
2:46 And if any of the threads come back and say yes, we're alive, then we want to wait a little bit. So let's wait, I don't know, five milliseconds.
2:56 Could even make it shorter, right? Actually waiting this little bit doesn't matter, right? So we've got three threads, we'll wait three milliseconds.
3:03 Just ask the question again Are these three threads alive? So you decide what number goes here, but it should be
3:09 probably pretty small. And then after this we want to check is the cancel thread alive? We'll say if not, the abort_thread is alive.
3:18 That's it. Under Print, canceling on your request. And that's it. We're going to stop joining the threads. If any of them happen to still be alive
3:30 we're going to print out something and if they are still alive after that, main thread Exits it aborts all of them because they're daemon threads.
3:36 Okay, phew, let's see if this works. Oh, do you know why it's not alive? We may have missed a little bitty important step
3:47 Is it alive? No it's not alive. Why is it not alive? It's not alive 'cause we have not started it. Now let's try.
3:56 Alright, so it's press Enter to cancel and now it's working If I come down here, say follow along. Boom. Cancel entering request, done. Right away.
4:07 Won't have to hit a weird Ctrl + C, wonder what happened We got to even print out the apps exiting. Here's your final report. We spent 7.8 seconds.
4:16 Do it again. I hit enter real quick, canceled right away. Of course if I just let it run, well, it'll take a moment
4:23 41 seconds or so for this to finish. That's enough time for us to go review what we did. It's a little bit of a hack, but if you want to be able to
4:33 ask the user or give them an option to cancel this fork join work well, we can create another thread whose sole purpose is to look for user input
4:43 assuming you're not getting it from other places at this point. And if it gets input, then it exits you know, it can even actually capture a value
4:49 and then give that value back if you really want it to we just don't care at this point. So we're going to use the any operation
4:56 on any of the threads alive. We're going to use the timeout feature, on join and then just give a really short timeout to say
5:04 let's just check really quick wait, give them a little time to run and then if our question thread, do you want to exit
5:11 is still running then we're not going to cancel. But if it is, we'll just cancel and get out. Maybe we want to do this in a different order?
5:19 I don't know. There's a tiny bit of race condition about potentially saying we canceled it just at the moment that it didn't cancel
5:26 but, you know, that's threading. It's tricky, and we're just going to leave it at this. But, here's a way in which we can use timeout, and input
5:35 but it could've been a signal from another service could've been our web service called and told our threads. There's all sorts of operations
5:40 that we could use to trigger the canceling of these threads. Cool little pattern there to make our threaded example even better.
5:48 Oh, and let's see what our outcome was. Look at that, it ran all the way to the end. It got to 400 twice, like it should.
5:54 And then it printed that it was done after about 20 seconds which is exactly what we expected. So here is the case where we did not cancel it.

Talk Python's Mastodon Michael Kennedy's Mastodon