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.