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