The correct approach is to use threading.Event. For example:

import threading

e = threading.Event()
e.wait(timeout=100)   # instead of time.sleep(100)

In the other thread, you need to have access to e. You can interrupt the sleep by issuing:

e.set()

This will immediately interrupt the sleep. You can check the return value of e.wait to determine whether it's timed out or interrupted. For more information refer to the documentation: https://docs.python.org/3/library/threading.html#event-objects .

Answer from He Shiming on Stack Overflow
🌐
Tutorialspoint
tutorialspoint.com › python › python_interrupting_thread.htm
Python - Interrupting a Thread
This may be for many reasons, such as − task completion, application shutdown, or other external conditions. In Python, interrupting threads can be achieved using threading.Event or by setting a termination flag within the thread itself.
Discussions

python - Is there any way to kill a Thread? - Stack Overflow
There are cases, however, when you really need to kill a thread. An example is when you are wrapping an external library that is busy for long calls, and you want to interrupt it. The following code allows (with some restrictions) to raise an Exception in a Python thread: More on stackoverflow.com
🌐 stackoverflow.com
multithreading - How to stop a looping thread in Python? - Stack Overflow
What's the proper way to tell a looping thread to stop looping? I have a fairly simple program that pings a specified host in a separate threading.Thread class. In this class it sleeps 60 seconds... More on stackoverflow.com
🌐 stackoverflow.com
How can i kill/stop a thread, in simple terms?
using KeyboardInterrupt More on reddit.com
🌐 r/learnpython
7
1
March 31, 2023
multithreading - python threading: how to interrupt the main thread and make it do something else - Stack Overflow
Using python threading, is it possible to interrupt the main thread without terminate it and ask it to do something else? For example, def watch(): while True: sleep(10) More on stackoverflow.com
🌐 stackoverflow.com
🌐
Python.org
discuss.python.org › ideas
What about interruptible threads - Ideas - Discussions on Python.org
July 15, 2022 - What about interruptible threads This post is to propose a feature rarely available in other languages, that I suppose could be considered “bad programming” by many. I’m conscious that topic could eventually be seen as g…
🌐
Python
docs.python.org › 3 › library › _thread.html
_thread — Low-level threading API — ...
A thread can use this function to interrupt the main thread, though there is no guarantee that the interruption will happen immediately. If given, signum is the number of the signal to simulate. If signum is not given, signal.SIGINT is simulated. If the given signal isn’t handled by Python (it ...
🌐
Gregoryzynda
gregoryzynda.com › python › developer › threading › 2018 › 12 › 21 › interrupting-python-threads.html
Interrupting Python Threads - Greg Zynda
This half-second timeout allows for our interrupt signal to be processed. If the KeyboardInterrupt signal is received, the thread’s alive attribute is set to False, signaling that work needs to stop. After the thread stops working it is joined back and the main process can exit. #!/usr/bin/env python from threading import Thread, current_thread from time import sleep import sys def main(): # Spawn a new thread that runs sleepy t = Thread(target=sleepy, args=(0,)) try: # Start the thread t.start() # If the child thread is still running while t.is_alive(): # Try to join the child thread back t
🌐
Super Fast Python
superfastpython.com › home › tutorials › interrupt the main thread in python
Interrupt the Main Thread in Python - Super Fast Python
September 12, 2022 - You can interrupt the main thread via the _thread.interrupt_main() function. In this tutorial you will discover how to interrupt the main thread from another thread in Python. Let’s get started.
Top answer
1 of 16
880

It is generally a bad pattern to kill a thread abruptly, in Python, and in any language. Think of the following cases:

  • the thread is holding a critical resource that must be closed properly
  • the thread has created several other threads that must be killed as well.

The nice way of handling this, if you can afford it (if you are managing your own threads), is to have an exit_request flag that each thread checks on a regular interval to see if it is time for it to exit.

For example:

import threading

class StoppableThread(threading.Thread):
    """Thread class with a stop() method. The thread itself has to check
    regularly for the stopped() condition."""

    def __init__(self,  *args, **kwargs):
        super(StoppableThread, self).__init__(*args, **kwargs)
        self._stop_event = threading.Event()

    def stop(self):
        self._stop_event.set()

    def stopped(self):
        return self._stop_event.is_set()

In this code, you should call stop() on the thread when you want it to exit, and wait for the thread to exit properly using join(). The thread should check the stop flag at regular intervals.

There are cases, however, when you really need to kill a thread. An example is when you are wrapping an external library that is busy for long calls, and you want to interrupt it.

The following code allows (with some restrictions) to raise an Exception in a Python thread:

def _async_raise(tid, exctype):
    '''Raises an exception in the threads with id tid'''
    if not inspect.isclass(exctype):
        raise TypeError("Only types can be raised (not instances)")
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid),
                                                     ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # "if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"
        ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), None)
        raise SystemError("PyThreadState_SetAsyncExc failed")

class ThreadWithExc(threading.Thread):
    '''A thread class that supports raising an exception in the thread from
       another thread.
    '''
    def _get_my_tid(self):
        """determines this (self's) thread id

        CAREFUL: this function is executed in the context of the caller
        thread, to get the identity of the thread represented by this
        instance.
        """
        if not self.is_alive(): # Note: self.isAlive() on older version of Python
            raise threading.ThreadError("the thread is not active")

        # do we have it cached?
        if hasattr(self, "_thread_id"):
            return self._thread_id

        # no, look for it in the _active dict
        for tid, tobj in threading._active.items():
            if tobj is self:
                self._thread_id = tid
                return tid

        # TODO: in python 2.6, there's a simpler way to do: self.ident

        raise AssertionError("could not determine the thread's id")

    def raise_exc(self, exctype):
        """Raises the given exception type in the context of this thread.

        If the thread is busy in a system call (time.sleep(),
        socket.accept(), ...), the exception is simply ignored.

        If you are sure that your exception should terminate the thread,
        one way to ensure that it works is:

            t = ThreadWithExc( ... )
            ...
            t.raise_exc( SomeException )
            while t.isAlive():
                time.sleep( 0.1 )
                t.raise_exc( SomeException )

        If the exception is to be caught by the thread, you need a way to
        check that your thread has caught it.

        CAREFUL: this function is executed in the context of the
        caller thread, to raise an exception in the context of the
        thread represented by this instance.
        """
        _async_raise( self._get_my_tid(), exctype )

(Based on Killable Threads by Tomer Filiba. The quote about the return value of PyThreadState_SetAsyncExc appears to be from an old version of Python.)

As noted in the documentation, this is not a magic bullet because if the thread is busy outside the Python interpreter, it will not catch the interruption.

A good usage pattern of this code is to have the thread catch a specific exception and perform the cleanup. That way, you can interrupt a task and still have proper cleanup.

2 of 16
201

A multiprocessing.Process can p.terminate()

In the cases where I want to kill a thread, but do not want to use flags/locks/signals/semaphores/events/whatever, I promote the threads to full blown processes. For code that makes use of just a few threads the overhead is not that bad.

E.g. this comes in handy to easily terminate helper "threads" which execute blocking I/O

The conversion is trivial: In related code replace all threading.Thread with multiprocessing.Process and all queue.Queue with multiprocessing.Queue and add the required calls of p.terminate() to your parent process which wants to kill its child p

See the Python documentation for multiprocessing.

Example:

import multiprocessing
proc = multiprocessing.Process(target=your_proc_function, args=())
proc.start()
# Terminate the process
proc.terminate()  # sends a SIGTERM
Find elsewhere
🌐
Miguel Grinberg
blog.miguelgrinberg.com › post › how-to-kill-a-python-thread
How to Kill a Python Thread - miguelgrinberg.com
October 19, 2020 - This solution effectively gives you an "interruptible" sleep, because if the event is set while the thread is stuck in the middle of the call to wait() then the wait will return immediately. Did you know about event objects in Python?
Top answer
1 of 8
172

Threaded stoppable function

Instead of subclassing threading.Thread, one can modify the function to allow stopping by a flag.

We need an object, accessible to running function, to which we set the flag to stop running.

We can use threading.currentThread() object.

import threading
import time


def doit(arg):
    t = threading.currentThread()
    while getattr(t, "do_run", True):
        print ("working on %s" % arg)
        time.sleep(1)
    print("Stopping as you wish.")


def main():
    t = threading.Thread(target=doit, args=("task",))
    t.start()
    time.sleep(5)
    t.do_run = False
    

if __name__ == "__main__":
    main()

The trick is, that the running thread can have attached additional properties. The solution builds on assumptions:

  • the thread has a property "do_run" with default value True
  • driving parent process can assign to started thread the property "do_run" to False.

Running the code, we get following output:

$ python stopthread.py                                                        
working on task
working on task
working on task
working on task
working on task
Stopping as you wish.

Pill to kill - using Event

Other alternative is to use threading.Event as function argument. It is by default False, but external process can "set it" (to True) and function can learn about it using wait(timeout) function.

We can wait with zero timeout, but we can also use it as the sleeping timer (used below).

def doit(stop_event, arg):
    while not stop_event.wait(1):
        print ("working on %s" % arg)
    print("Stopping as you wish.")


def main():
    pill2kill = threading.Event()
    t = threading.Thread(target=doit, args=(pill2kill, "task"))
    t.start()
    time.sleep(5)
    pill2kill.set()
    t.join()

Edit: I tried this in Python 3.6. stop_event.wait() blocks the event (and so the while loop) until release. It does not return a boolean value. Using stop_event.is_set() works instead.

Stopping multiple threads with one pill

Advantage of pill to kill is better seen, if we have to stop multiple threads at once, as one pill will work for all.

The doit will not change at all, only the main handles the threads a bit differently.

def main():
    pill2kill = threading.Event()
    tasks = ["task ONE", "task TWO", "task THREE"]

    def thread_gen(pill2kill, tasks):
        for task in tasks:
            t = threading.Thread(target=doit, args=(pill2kill, task))
            yield t

    threads = list(thread_gen(pill2kill, tasks))
    for thread in threads:
        thread.start()
    time.sleep(5)
    pill2kill.set()
    for thread in threads:
        thread.join()
2 of 8
32

This has been asked before on Stack. See the following links:

  • Is there any way to kill a Thread in Python?
  • Stopping a thread after a certain amount of time

Basically you just need to set up the thread with a stop function that sets a sentinel value that the thread will check. In your case, you'll have the something in your loop check the sentinel value to see if it's changed and if it has, the loop can break and the thread can die.

🌐
Alexandra Zaharia
alexandra-zaharia.github.io › posts › how-to-stop-a-python-thread-cleanly
How to stop a Python thread cleanly | Alexandra Zaharia
December 31, 2021 - Here is what happens when stopping it via a keyboard interrupt (... denotes output that was snipped for readability purposes): The first Ctrl + C stops the main program, but not the thread. The second time, the thread is stopped as well. The Python threading documentation explains that a thread may be started as a daemon, meaning that “the entire Python program exits when only daemon threads are left”. The main program itself is not a daemon thread.
🌐
GeeksforGeeks
geeksforgeeks.org › python-different-ways-to-kill-a-thread
Python | Different ways to kill a Thread - GeeksforGeeks
August 9, 2024 - In the above code, as soon as the global variable stop_threads is set, the target function run() ends and the thread t1 can be killed by using t1.join(). But one may refrain from using global variable due to certain reasons. For those situations, function objects can be passed to provide a similar functionality as shown below. ... # Python program killing # threads using stop # flag import threading import time def run(stop): while True: print('thread running') if stop(): break def main(): stop_threads = False t1 = threading.Thread(target = run, args =(lambda : stop_threads, )) t1.start() time.sleep(1) stop_threads = True t1.join() print('thread killed') main()
🌐
Blogger
snakesthatbite.blogspot.com › 2010 › 09 › cpython-threading-interrupting.html
Snakes that Bite: CPython Threading: Interrupting
You are probably aware (or have guessed) by now that there is no Thread.stop() method in Python (and the one in Java is deprecated and generally considered a Bad Idea™). So what you must do is to implement a "thread interruption policy" which in our case is basically a signaling mechanism that the main thread can use to tell the worker thread to stop.
🌐
Blogger
pydev.blogspot.com › 2013 › 01 › interrupting-python-thread-with-signals.html
PyDev adventures: Interrupting a Python thread with signals
January 17, 2013 - import time import sys import threading class SigFinish(Exception): pass def throw_signal_function(frame, event, arg): raise SigFinish() def do_nothing_trace_function(frame, event, arg): # Note: each function called will actually call this function # so, take care, your program will run slower because of that. return None def interrupt_thread(thread): for thread_id, frame in sys._current_frames().items(): if thread_id == thread.ident: # Note: Python 2.6 onwards set_trace_for_frame_and_parents(frame, throw_signal_function) def set_trace_for_frame_and_parents(frame, trace_func): # Note: this onl
🌐
docs.python.org
docs.python.org › 3 › library › thread.html
_thread — Low-level threading API
A thread can use this function to interrupt the main thread, though there is no guarantee that the interruption will happen immediately. If given, signum is the number of the signal to simulate. If signum is not given, signal.SIGINT is simulated. If the given signal isn’t handled by Python (it ...
🌐
Python Tutorial
pythontutorial.net › home › python concurrency › how to stop a thread in python
How to Stop a Thread in Python by Examples
June 3, 2023 - Summary: in this tutorial, you’ll learn how to stop a thread in Python from the main thread using the Event class of the threading module.
Top answer
1 of 1
1

I think below code will solve your problem.

We need to konow that :

Python signal handlers are always executed in the main Python thread of the main interpreter, even if the signal was received in another thread

We send our process SIGUSR1 signal in the subthread.

The SIGUSR1 and SIGUSR2 signals are set aside for you to use any way you want. They’re useful for simple interprocess communication, if you write a signal handler for them in the program that receives the signal.

In our case this signals will be handled in the main thread. When subthread send signal to own process, signal handler run in the main thread and we will throw an exception in the signal handler. After that exception, your do_Something() catch this exception and will enter to SubThreadException block, in this block you can do some cleanup. After the cleanup() we throw the SubThreadException again because we need to run your doSomethingElse() func.

class SubThreadException(Exception):
    pass

def usr1_handler(signum, frame):
    raise SubThreadException()

signal.signal(signal.SIGUSR1,usr1_handler) 

def watch():
    while True:
        sleep(10)
        somethingWrong = check()
        if somethingWrong:
            os.kill(os.getpid(),signal.SIGUSR1)
                    
def doSomething():
    try:
        #your work here
    except SubThreadException:
        cleanup() #your cleanup, like close the file,flush the buffer
        raise SubThreadException
        
try:
    watcher = threading.Thread(target=watch)
    watcher.start()
    doSomething() # This function could run several days and it cannot detect something wrong within itself, so I need the other thread watcher to check if this function perform well. In case of malfunction, the watcher should interrupt this function and ask the main thread to doSomethingElse
except SubThreadException:
    doSomethingElse()

But there are some cases as noted in the python signal module doc :

If a signal handler raises an exception, the exception will be propagated to the main thread and may be raised after any bytecode instruction. Most notably, a KeyboardInterrupt may appear at any point during execution. Most Python code, including the standard library, cannot be made robust against this, and so a KeyboardInterrupt (or any other exception resulting from a signal handler) may on rare occasions put the program in an unexpected state

Top answer
1 of 2
82

A similar question is "How do you kill a thread?"

You create an exit handler in your thread that is controlled by a lock or event object from the threading module. You then simply remove the lock or signal the event object. This informs the thread it should stop processing and exit gracefully. After signaling the thread in your main program, the only thing left to do is to use the thread.join() method in main which will wait for the thread to shut down.

A short example:

import threading
import time

def timed_output(name, delay, run_event):
    while run_event.is_set():
        time.sleep(delay)
        print name,": New Message!"


def main():
    run_event = threading.Event()
    run_event.set()
    d1 = 1
    t1 = threading.Thread(target = timed_output, args = ("bob",d1,run_event))

    d2 = 2
    t2 = threading.Thread(target = timed_output, args = ("paul",d2,run_event))

    t1.start()
    time.sleep(.5)
    t2.start()

    try:
        while 1:
            time.sleep(.1)
    except KeyboardInterrupt:
        print "attempting to close threads. Max wait =",max(d1,d2)
        run_event.clear()
        t1.join()
        t2.join()
        print "threads successfully closed"

if __name__ == '__main__':
    main()

If you REALLY need the functionality of killing a thread, use multiprocessing. It allows you to send SIGTERMs to individual "processes" (it's also very similar to the threading module). Generally speaking, threading is for when you are IO-bound, and multiprocessing is for when you are truly processor-bound.

2 of 2
6

There are a couple of options that don't require using locks or other signals between threads. One is setting the threads as daemons, which will be killed off automatically when the main thread exits. The other is using processes instead, which have a terminate method you can call from the main process, if you needed to kill them and keep the main program running.

Both of these are especially useful if you have threads blocking on input. While using a timeout and periodically checking the signal would work in most cases without too much overhead, using daemons or processes eliminates the need for any busy loops or significant added complexity.

See the answers to this question for more details on these solutions and discussion on the problem of killing threads.

🌐
Super Fast Python
superfastpython.com › stop-a-thread-in-python
How to Stop a Thread in Python – SuperFastPython
March 20, 2022 - In concurrent programming, we may run a task in a new thread, then later decide to stop the task. ... The result from the task is no longer required. The application is shutting down. The outcome from the task has gone astray. Python provides no way to stop a running thread in the API.