How kill a Thread?


when I try this example from: Is there any way to kill a Thread?

import threading
import time

def my_function():
    print("Thread is running")
    print("Thread is done")

my_thread = threading.Thread(target=my_function)
print("Thread is killed")

I got:

Thread is running
Thread is killed
Thread is done

It’s my understanding that if indeed the Thread was killed , I should not have “Thread is done” !!

Any other way to kill a Thread ?

What you did there was join with a timeout: threading — Thread-based parallelism — Python 3.12.1 documentation This doesn’t kill the thread; it waits for it to finish, but will only wait for that many seconds. Since the thread hadn’t finished, it returns after five seconds, but with the thread still alive.

There’s no standard way to forcibly kill a thread. Generally you need to write your own in some way. It’s a bit unfortunate (this feature would be rather handy), but it’s hard to do this reliably on all operating systems. There are some dirty hacks out there, to be sure, and they might work, but I would just make something cooperative (such as a core loop that periodically checks for an abort flag).

this feature would be rather handy

This is a big can of worms!

Java 1.0 had this feature, and it almost immediately got deprecated, because you had no idea what your thread might be doing at the instant it was killed, and it was too easy to leave things in a bad state when the thread suddenly terminated.

In Python, the way this would have been accomplished would be with a similar BaseException to KeyboardInterrupt, one that can be injected into a thread and raised at any point, but that still might leave things in a bad state (though you could fix that with finally perhaps).

A loop with a condition variable is a very safe way to write a killable thread and the only one that is universal across platforms and languages. When the condition is seen to change, you are at the end of your loop, everything is clean, and you can just exit.

Yeah, if I were implementing it, my first exploration would be: Every time you check for KeyboardInterrupt, also check for “please abort this thread”, and if so, reset the flag and raise ThreadTermination.

I’ve got a little RunState class for this kind of thing. It does a few
small things, but one is that is has a .cancelled property you can
query. An outside thing (eg another thread) can set that, and you just
poll it at suitable points. It’s got a little .raiseif() method to do
that poll and raise a CancellationError if true, which makes for a
succinct poll.

In command line scripts I make one of these and add a signal handler for
SIGINT which sets the cancellation flag. So it doesn’t get used just
for threads, it’s also the mechanism for plain old unthreaded early
termination in my scripts.

Cameron Simpson

Well, yes. The entire point of the discussion at the other link, is that there is not any way to really kill a thread in the way you describe - by design. It’s difficult or impossible to write correct code if we have such functionality to kill one thread from code that’s running in another - because there’s no way for each thread to know “where” the other threads are in their calculation, or whether it’s safe to stop at that point right now.

The Global Interpreter Lock (GIL) lets us avoid some of the nastier consequences of this, but it’s easy to imagine a thread that does some calculation that can’t correctly be stopped except at very specific points, because otherwise it will leave objects in an inconsistent or nonsensical state. For example, imagine if we had a thread that was adding nodes to a linked list or some other data structure, and another thread tried to kill it in the middle of the re-linking process.

Of course, a thread can easily kill itself, by just arranging so that it doesn’t do any more work. For example, it could return from everything, or wrap its outermost code in a try/except for a custom exception and then raise that exception to abort the process. It can even use sys.exit, which despite what it sounds like is thread-local:

>>> import sys, threading
>>> def worker():
...     print('before abort')
...     sys.exit()
...     print('after abort')
>>> threading.Thread(target=worker).start()
before abort
>>> # interpreter is still running
>>> sys.exit() # from here, will exit the interpreter

That works by basically the same exception trick: it raises SystemExit, and the default uncaught-exception handler special-cases that and doesn’t show a traceback.

But to “kill” a different thread, we should let that thread be responsible for deciding when it should stop. The join method for threads simply means to wait until the other thread stops; but we can do things like set some kind of “signal” for the other thread; write that thread’s code so that it checks for the signal at appropriate times; and then use join.