977

Is it possible to terminate a running thread without setting/checking any flags/semaphores/etc.?

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
Sudden Def
  • 10,031
  • 3
  • 18
  • 8

31 Answers31

837

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.isAlive():
            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 raiseExc(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.raiseExc( SomeException )
            while t.isAlive():
                time.sleep( 0.1 )
                t.raiseExc( 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.

Grigory Zhadko
  • 1,484
  • 1
  • 19
  • 33
Philippe F
  • 11,776
  • 5
  • 29
  • 30
  • 3
    This code doesn't quite work. You need to convert the tid to long like: ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), None) –  May 21 '11 at 07:28
  • 3
    @Bluebird75: In the first example, why use a `threading.Event` instead of a simple boolean attribute `stopped` that can be checked from inside the thread? – Eric O. Lebigot Jul 14 '11 at 16:48
  • 130
    @Bluebird75: Furthermore, I'm not sure I get the argument that threads should not be killed abruptly "because the thread might be holding a critical resource that must be closed properly": this is also true from a main program, and main programs can be killed abruptly by the user (Ctrl-C in Unix, for instance)–in which case they try to handle this possibility as nicely as possible. So, I fail to see what is special with threads, and why they should not receive the same treatment as main programs (namely that they can be killed abruptly). :) Could you elaborate on this? – Eric O. Lebigot Jul 14 '11 at 16:53
  • 3
    @EOL: there is no specific advantage of using a threading.Event here indeed as far as I remember. – Philippe F Aug 02 '11 at 09:36
  • @EOL: Let's take the case of a thread that opens a remote resource (DB connection an another server), which has a 5 minutes timeout, and maximum number of connection set to 20 per users. If your program opens 5 threads with 5 connections and you kill it abruptly without proper thread closing, your program won't be able to connect the 5th time you launch it in a 5 minutes interval. So, in this case, you need proper thread closing (and program closing). – Philippe F Aug 02 '11 at 09:43
  • 22
    @EOL: On the other hand, if all the resources that the thread is owning are local resources (open files, sockets), Linux is reasonably good at the process cleanup and this does not leak. I had cases though where I created a server using socket, and if I do a brutal interruption with Ctrl-C, I can non longer launch the program because it can not binds the socket. I need to wait 5 minutes. Proper solution was to catch Ctrl-C and do clean socket deconnection. – Philippe F Aug 02 '11 at 09:45
  • @Bluebird75: Thank you for the discussion. :) Did the server program that you mention use threads, or was it a main program (that did not properly release the socket binding)? – Eric O. Lebigot Aug 03 '11 at 02:07
  • 12
    @Bluebird75: btw. you can use `SO_REUSEADDR` socket option to avoid `Address already in use` error. – Messa Sep 11 '11 at 09:09
  • 13
    Note about this answer: at least for me (py2.6), I had to pass `None` instead of `0` for the `res != 1` case, and I had to call `ctypes.c_long(tid)` and pass that to any ctypes function rather than the tid directly. – Walt W Nov 17 '11 at 21:16
  • 23
    Its worth mentioning that _stop is already occupied in the Python 3 threading library. As such, maybe use a different variable otherwise you will get an error. – diedthreetimes Jan 18 '13 at 01:51
  • 2
    @Messa, SO_REUSEADDR does not always work and besides, that's beside the point - sockets are just an example of a pattern of where it can be a good idea to close resources properly. You can of course turn off power to the computer, then boot it up again. The filesystem will recover, if it has logging. – Prof. Falken May 30 '13 at 06:44
  • I'd be interested in the case that "if the thread is busy outside the python interpreter, it will not catch the interruption". Doesn't it catch it at all, or will it catch it at some time later? I tested it, and it seems that eventually it will catch it, but some seconds later. – glglgl Sep 01 '13 at 07:54
  • @glglgl: the discussion becomes beyond my technical knowledge. Initially, I just copy/pasted some code that I found on ActiveState. I use it only within the test suite of a program, so it is not a big problem for me if this is only 80% reliable. A best place to ask this is comp.lang.python... – Philippe F Sep 02 '13 at 10:25
  • 4
    I disagree. When you say "kill a thread" - you really mean "send a signal to a thread". (This could be the magic #9, or preferably another). There are plenty of times when this is warranted. For example, if the thread is in some sort of a blocking syscall, one would *need* to be able to send it a signal to pop it out, even in-conjunction with a "graceful" mechanism to exit a [polling] thread. – Brad Sep 13 '13 at 19:33
  • 1
    I'm using something like this to give my threads a KeyboardInterrupt so they've a chance to clean up. If they're STILL hanging after that, then SystemExit is appropriate, or just kill the process from a terminal. – drevicko Nov 21 '13 at 01:02
  • Most muiltithreading requires a some kind of .join(). This example does not deal with it processing block if a signal comes in on the main thread such as sigint. – dman Nov 30 '13 at 02:54
  • Wasn't sure about the "wait for the thread to exit properly using join()" sentence in the answer. I understand the implementation is `thread1.join()`, `thread2.join()`, etc., as shown [here](http://stackoverflow.com/a/11968818/404469). – gary Jun 20 '14 at 17:34
  • What needs to be the sending parameter?For me it works only for the thread itself, in this case: `self.thr = ThreadedTask(self.q)`, `self.thr.start()`, `print(ThreadedTask.stopped(self.thr))`, `ThreadedTask.stop(self.thr)`, `print(ThreadedTask.stopped(self.thr))` when i print it like that, the first one print false, second one true. Everything is ok, but my thread keeps running. I am writing simple server/client app with gui.And my thread process the logic of the server, waiting on sockets, accept them and answer. And it keeps accepting and answering on sockets. But stopped is true – tomdelahaba Jan 24 '15 at 11:50
  • 3
    I like the `StoppableThread` approach. I added a class `class ThreadKilled(KeyboardInterrupt): pass` and added `def sleep(self, time): self._stop.wait(time); if self.stopped(): raise ThreadKilled`. That way, so long as the thread replaces calls to `time.sleep(t)` with `self.sleep(t)`, the thread can be killed from a long sleep. From there, I went on to use `Queue.Queue` in place of `threading.Event` as that gives the same base functionality (including `sleep(t)`) but also lets the thread be a consumer. – Ben May 22 '15 at 12:33
  • 1
    Also, I added `killAndJoin`, `__enter__` and `__exit__` methods, where `__exit__` calls `killAndJoin`. This way, the main thread can use a `with` statement on a bunch of worker threads to have them cleanly stop and clean up after themselves. – Ben May 22 '15 at 12:36
  • As a technical detail, can anyone explain why `PyThreadState_SetAsyncExc` seems to not kill a `while True: time.sleep(1)` thread instantly? Is the internals of `time.sleep(1)` not in Python and so it has to finish sleeping? It seems weird given you can `ctrl+C` out of `time.sleep`; why wouldn't you be able to similarly interrupt a thread? – Ben May 22 '15 at 12:38
  • 3
    @Ben It is because when you raise an exception in a thread, it is a Python exception that can only be accessed via the Python interpreter. Since `time.sleep` is an external C function that releases the GIL, it won't realize that it has had an exception until the function returns, reacquires the GIL and runs the Python bytecode interpreter. `Ctrl+C` causes a system level signal to be fired, which is *then* translated into a Python exception. That is why it works with `time.sleep`. – eestrada Nov 16 '15 at 22:54
  • @diedthreetimes: I edited the answer to fix the `_stop` naming issue. – Jérôme May 09 '17 at 19:48
  • What's the point of using an Event for `_stop_event`? It is never waited for? Why not just use a boolean attribute as a flag? – Jérôme May 09 '17 at 19:49
  • kill -9 is not humane, but sometimes we have to (like now - I can either kill some ten threads I've created by mistake or kill the hosting process...) – Ofer Rahat Dec 05 '17 at 09:56
  • 1
    Your answer is correct, but you're missing a point here: There are situations when your thread may get stuck in the shutdown process (OK, most times it's due to bad design and forgotten things, but it may always happen). When I've to design a critical process, I implement my standard gracefull stop and join methods, however, if the code is important enough, it's also worth to implement a terminate() method which properly terminates() any process the about-to-be-killed process has created. This way, is something goes wrong (ie some unforseen Exception not being properly handled during (...) – DGoiko Jan 18 '19 at 16:37
  • (...) termination. In those cases, I can detect a "properly ended" condition and safelly terminate the thread if it is not met, freeing all the resources in a forcefully and safer way. You could argue that a proper design would handle this situation within the gracefull stop process, and I totally agree with you, in fact, I usually do it in both places when I need to be absolutely sure that the thing will be bullet-proof. – DGoiko Jan 18 '19 at 16:39
  • 2
    There really should be a standard library way to send asynchronous signals to Python threads. If you want to make this feature safe, then we need to follow the C example with pselect or Haskell with masking and brackets. At any case, it's very awkward when a thread is doing a blocking operation and there's no way to tell it to stop what it's doing without resorting to hacks like sentinel values or rewriting Python's exception mechanism to raise exceptions (although a standard library way of throwing exceptions to threads works too). – CMCDragonkai Apr 05 '19 at 03:24
  • 2
    @Jérôme: On CPython, a simple boolean is fine as written. But using an `Event` means: 1) A thread that needs to sleep for a while can replace `time.sleep` with a call to the `wait` method of the `Event` with a `timeout`, allowing it to wake instantly if it's told to exit, and 2) On non-CPython interpreters that JIT, the GIL doesn't exist to provide protections like ensuring a write in one thread is seen by another (if the code is fully compiled, it could read the boolean once and assume it never needed to read it again, just like C code w/o atomics does). `Event`s don't have that problem. – ShadowRanger Feb 05 '20 at 14:22
  • What if I want to catch the exception with this code? Should it be done outside of the thread (`try: t.start() except SomException...`) or in the function wrapped by the thread? (`def func(): try: ... except SomeException ...; t = ThreadWithExc(target=func) ...`? Or somewhere else? – Michele Piccolini Feb 19 '20 at 12:25
  • 1
    Regarding subclassing `threading.Thread` as is done above, the python stdlib [docs](https://docs.python.org/3/library/threading.html#thread-objects) say "No other methods (except for the constructor) should be overridden in a subclass. In other words, only override the __init__() and run() methods of this class." Not sure I'd be able to sleep at night after directly disobeying the python docs. – Jasha Dec 30 '20 at 07:05
  • I don't see anything here that helps if you have a thread blocking on IO. For example, how do you interrupt a thread that called `read()` on a socket? – Edward Ned Harvey Oct 04 '21 at 10:21
  • Shame I have "bad patterns" in my tests... Thank you – Adonis Mar 30 '22 at 14:56
  • Tested with Python 3.8.8: the exception can even interrupt `time.sleep()`! – Daniel Chin Oct 18 '22 at 05:15
  • Thank you. Why the thread can exit properly using ` join()` – Avv Nov 01 '22 at 15:38
  • How can the worker function access the `.self.stopped`? There is a circular dependency, since the thread object itself has to be passed to the init: `task = StoppableThread(task_id=task_id, target=task_function, args=(task, task_args))` – Gulzar Jul 27 '23 at 21:53
170

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
kolypto
  • 31,774
  • 17
  • 105
  • 99
cfi
  • 10,915
  • 8
  • 57
  • 103
  • Thanks. I replaced queue.Queue with multiprocessing.JoinableQueue and followed this answer: http://stackoverflow.com/a/11984760/911207 – David Braun Aug 15 '14 at 17:30
  • 28
    `multiprocessing` is nice, but be aware that arguments is pickled to the new process. So if one of the arguments is something not-pickable (like a `logging.log`) it might not be a good idea to use `multiprocessing`. – Lyager Apr 09 '18 at 09:10
  • 8
    `multiprocessing` arguments are pickled to the new process on Windows, but Linux uses forking to copy them (Python 3.7, unsure what other versions). So you'll end up with code that works on Linux but raises pickle errors on Windows. – nyanpasu64 Apr 18 '19 at 22:21
  • `multiprocessing` with logging is tricky business. Need to use `QueueHandler` (see [this tutorial](https://docs.python.org/3/howto/logging-cookbook.html#logging-to-a-single-file-from-multiple-processes)). I learned it the hard way. – Fanchen Bao Dec 09 '19 at 00:10
  • Shame I can't spy on functions ran in multiprocessing... Thank you – Adonis Mar 30 '22 at 14:56
139

There is no official API to do that, no.

You need to use platform API to kill the thread, e.g. pthread_kill, or TerminateThread. You can access such API e.g. through pythonwin, or through ctypes.

Notice that this is inherently unsafe. It will likely lead to uncollectable garbage (from local variables of the stack frames that become garbage), and may lead to deadlocks, if the thread being killed has the GIL at the point when it is killed.

Martin v. Löwis
  • 124,830
  • 17
  • 198
  • 235
103

If you are trying to terminate the whole program you can set the thread as a "daemon". see Thread.daemon

schettino72
  • 2,990
  • 1
  • 28
  • 27
  • This doesn't make any sense. The documentation clearly states, "this must be set before start() is called, otherwise RuntimeError is raised." Thus, if I want to kill a thread that was not originally a daemon, how can I use this? – Raffi Khatchadourian Nov 29 '11 at 19:21
  • 42
    Raffi I think he's suggesting you would set it in advance, knowing that when your main thread exits you also want the daemon threads to exit. – fantabolous Jul 31 '14 at 07:06
  • 3
    Isn't setting a thread as a daemon something you would do in case you want the thread to keep running even if your main program shuts down? – Michele Piccolini Feb 19 '20 at 09:41
  • 5
    @MichelePiccolini: It’s the opposite: daemon threads *don’t* keep the process running when the others are gone. – Davis Herring May 02 '20 at 01:57
  • 2
    This was the best answer for me, I just wanted to cleanup threads when the parent process shuts down. Thanks! – Lin Meyer Mar 20 '21 at 13:49
  • @DavisHerring what you said does not necessarily contradict what michelle said if the daemon threads can run without the main process. – fuzzyTew Dec 03 '21 at 00:17
  • Exactly what I needed! I new there was nothing important going on in the child thread and just wanted it to exit when the tkinter gui exited. – tarikki Mar 04 '22 at 06:17
88

As others have mentioned, the norm is to set a stop flag. For something lightweight (no subclassing of Thread, no global variable), a lambda callback is an option. (Note the parentheses in if stop().)

import threading
import time

def do_work(id, stop):
    print("I am thread", id)
    while True:
        print("I am thread {} doing something".format(id))
        if stop():
            print("  Exiting loop.")
            break
    print("Thread {}, signing off".format(id))


def main():
    stop_threads = False
    workers = []
    for id in range(0,3):
        tmp = threading.Thread(target=do_work, args=(id, lambda: stop_threads))
        workers.append(tmp)
        tmp.start()
    time.sleep(3)
    print('main: done sleeping; time to stop the threads.')
    stop_threads = True
    for worker in workers:
        worker.join()
    print('Finis.')

if __name__ == '__main__':
    main()

Replacing print() with a pr() function that always flushes (sys.stdout.flush()) may improve the precision of the shell output.

(Only tested on Windows/Eclipse/Python3.3)

Jon Coombs
  • 2,135
  • 2
  • 25
  • 26
52

In Python, you simply cannot kill a Thread directly.

If you do NOT really need to have a Thread (!), what you can do, instead of using the threading package , is to use the multiprocessing package . Here, to kill a process, you can simply call the method:

yourProcess.terminate()  # kill the process!

Python will kill your process (on Unix through the SIGTERM signal, while on Windows through the TerminateProcess() call). Pay attention to use it while using a Queue or a Pipe! (it may corrupt the data in the Queue/Pipe)

Note that the multiprocessing.Event and the multiprocessing.Semaphore work exactly in the same way of the threading.Event and the threading.Semaphore respectively. In fact, the first ones are clones of the latters.

If you REALLY need to use a Thread, there is no way to kill it directly. What you can do, however, is to use a "daemon thread". In fact, in Python, a Thread can be flagged as daemon:

yourThread.daemon = True  # set the Thread as a "daemon thread"

The main program will exit when no alive non-daemon threads are left. In other words, when your main thread (which is, of course, a non-daemon thread) will finish its operations, the program will exit even if there are still some daemon threads working.

Note that it is necessary to set a Thread as daemon before the start() method is called!

Of course you can, and should, use daemon even with multiprocessing. Here, when the main process exits, it attempts to terminate all of its daemonic child processes.

Finally, please, note that sys.exit() and os.kill() are not choices.

vallentin
  • 23,478
  • 6
  • 59
  • 81
Paolo Rovelli
  • 9,396
  • 2
  • 58
  • 37
  • I don't know why people don't vote this up. What's wrong with this answer? This one works for me though. – fsevenm Sep 10 '20 at 12:51
  • 5
    @fsevenm: Processes are the same as threads. They run in separate memory-spaces, so there's no easy sharing of global variables. and passing arguments involves pickling them and unpickling them on the other side. That plus the overhead of starting up and running separate processes involves a lot more other overhead that simply switching threads does. It's apple vs oranges in many respects, so that is probably why — to answer your question. – martineau Nov 28 '20 at 23:36
  • @martineau I never said they were the same things. I actually started with a _"If you do NOT really need to have a Thread"_, because that's not always the case, and then continue with a _"If you REALLY need to use a Thread"_... – Paolo Rovelli May 08 '21 at 12:01
  • @PaoloRovelli: In the first part of my comment, I meant to write "Processes **aren't** the same as threads." – martineau May 08 '21 at 15:18
45

This is based on the thread2 -- killable threads ActiveState recipe.

You need to call PyThreadState_SetAsyncExc(), which is only available through the ctypes module.

This has only been tested on Python 2.7.3, but it is likely to work with other recent 2.x releases. PyThreadState_SetAsyncExc() still exists in Python 3 for backwards compatibility (but I have not tested it).

import ctypes

def terminate_thread(thread):
    """Terminates a python thread from another thread.

    :param thread: a threading.Thread instance
    """
    if not thread.isAlive():
        return

    exc = ctypes.py_object(SystemExit)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
        ctypes.c_long(thread.ident), exc)
    if res == 0:
        raise ValueError("nonexistent 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(thread.ident, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")
martineau
  • 119,623
  • 25
  • 170
  • 301
Johan Dahlin
  • 25,300
  • 6
  • 40
  • 55
  • I'm using something like this to give my threads a `KeyboardInterrupt` so they've a chance to clean up. If they're STILL hanging after that, then `SystemExit` is appropriate, or just kill the process from a terminal. – drevicko Nov 21 '13 at 01:01
  • This works if the thread is currently executing. It does not work if the thread is in a syscall; the exception will be silently ignored. – Matthias Urlichs Jun 22 '14 at 16:08
  • 1
    @JohanDahlin You could wait a bit (which, if you want to retry, you need to do anyway) and then do the isAlive() test. In any case, while this would work, I also wouldn't guarantee that it doesn't leave dangling references around. While it's possible in theory to make thread killing safe in CPython, by judicious use of `pthread_cleanup_push()/_pop()`, it'd be a lot of work to implement correctly and it would slow down the interpreter noticably. – Matthias Urlichs Jul 11 '14 at 01:00
35

You should never forcibly kill a thread without cooperating with it.

Killing a thread removes any guarantees that try/finally blocks set up so you might leave locks locked, files open, etc.

The only time you can argue that forcibly killing threads is a good idea is to kill a program fast, but never single threads.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • 32
    Why is it so hard to just tell a thread, please kill yourself when you finish your current loop... I don't get it. – Mehdi Apr 08 '16 at 14:37
  • 5
    There is no mechanism built into the cpu to identify a "loop" as such, the best you can hope for is to use some kind of signal that the code that is currently inside the loop will check once it exits. The correct way to handle thread synchronization is by cooperative means, the suspension, resuming, and killing of threads is functions that are meant for debuggers and the operating system, not application code. – Lasse V. Karlsen Apr 08 '16 at 18:39
  • 5
    @Mehdi: if I (personally) am writing the code in the thread, yes, I agree with you. But there are cases where I'm running third party libraries, and I don't have access to that code's execution loop. That is one use case for the requested feature. – Dan H Oct 13 '17 at 14:16
  • 1
    @DanH It is **even worst** with third party code as you have no idea what damage it can cause. If your third party library is not robust enough that it require to be killed, then you should do one of these: (1) ask the author to fix the problem, (2) use something else. If you really have no choice, then putting that code in a distinct process should be safer as some resources are shared only within a single process. – Phil1970 Dec 24 '18 at 19:47
  • if I have connection thread in the app and I want to close it. And it's a daemon. How can I close it afterall? Im not closing the app, I just need to cancel the connection. – aleXela Jul 15 '22 at 20:51
  • @aleXela You do exactly that, you close the connection object, this should make the thread fail. Or, you add a signal you can set that the thread is also checking, that makes it terminate peacefully. – Lasse V. Karlsen Jul 22 '22 at 07:35
27

If you are explicitly calling time.sleep() as part of your thread (say polling some external service), an improvement upon Phillipe's method is to use the timeout in the event's wait() method wherever you sleep()

For example:

import threading

class KillableThread(threading.Thread):
    def __init__(self, sleep_interval=1):
        super().__init__()
        self._kill = threading.Event()
        self._interval = sleep_interval

    def run(self):
        while True:
            print("Do Something")

            # If no kill signal is set, sleep for the interval,
            # If kill signal comes in while sleeping, immediately
            #  wake up and handle
            is_killed = self._kill.wait(self._interval)
            if is_killed:
                break

        print("Killing Thread")

    def kill(self):
        self._kill.set()

Then to run it

t = KillableThread(sleep_interval=5)
t.start()
# Every 5 seconds it prints:
#: Do Something
t.kill()
#: Killing Thread

The advantage of using wait() instead of sleep()ing and regularly checking the event is that you can program in longer intervals of sleep, the thread is stopped almost immediately (when you would otherwise be sleep()ing) and in my opinion, the code for handling exit is significantly simpler.

SCB
  • 5,821
  • 1
  • 34
  • 43
  • 5
    why was this post downvoted? What's wrong w/ this post? It look exactly like what I need.... – JDOaktown Aug 29 '18 at 17:57
  • While this post was not what I needed (I need to safely interrupt the parent from the child), I was definitely using `time.sleep` in other parts of my code and making the polling interval small so my script would react faster, however this solution has all the benefits of making a small polling interval with none of the drawbacks (wasted computation). +1 Thanks a lot. – A Kareem Dec 25 '20 at 12:53
20

You can kill a thread by installing trace into the thread that will exit the thread. See attached link for one possible implementation.

Kill a thread in Python

Jeff
  • 12,147
  • 10
  • 51
  • 87
Kozyarchuk
  • 21,049
  • 14
  • 40
  • 46
  • 2
    One of the few answers here that actually WORKS – Ponkadoodle Jul 04 '13 at 01:53
  • 8
    Two problems with this solution: (a) installing a tracer with sys.settrace() will make your thread run slower. As much as 10 times slower if it's compute bound. (b) won't affect your thread while it's in a system call. – Matthias Urlichs Jun 22 '14 at 16:22
  • Another problem with the linked recipe is that it overrides the `start()` method, whereas the [current documentation](https://docs.python.org/3/library/threading.html#thread-objects) explicitly states "In other words, _only_ override the `__init__()` and `run()` methods of this class" (when defining a subclass). – martineau Nov 28 '20 at 23:44
12

It is definitely possible to implement a Thread.stop method as shown in the following example code:

import sys
import threading
import time


class StopThread(StopIteration):
    pass

threading.SystemExit = SystemExit, StopThread


class Thread2(threading.Thread):

    def stop(self):
        self.__stop = True

    def _bootstrap(self):
        if threading._trace_hook is not None:
            raise ValueError('Cannot run thread with tracing!')
        self.__stop = False
        sys.settrace(self.__trace)
        super()._bootstrap()

    def __trace(self, frame, event, arg):
        if self.__stop:
            raise StopThread()
        return self.__trace


class Thread3(threading.Thread):

    def _bootstrap(self, stop_thread=False):
        def stop():
            nonlocal stop_thread
            stop_thread = True
        self.stop = stop

        def tracer(*_):
            if stop_thread:
                raise StopThread()
            return tracer
        sys.settrace(tracer)
        super()._bootstrap()

###############################################################################


def main():
    test1 = Thread2(target=printer)
    test1.start()
    time.sleep(1)
    test1.stop()
    test1.join()
    test2 = Thread2(target=speed_test)
    test2.start()
    time.sleep(1)
    test2.stop()
    test2.join()
    test3 = Thread3(target=speed_test)
    test3.start()
    time.sleep(1)
    test3.stop()
    test3.join()


def printer():
    while True:
        print(time.time() % 1)
        time.sleep(0.1)


def speed_test(count=0):
    try:
        while True:
            count += 1
    except StopThread:
        print('Count =', count)

if __name__ == '__main__':
    main()

The Thread3 class appears to run code approximately 33% faster than the Thread2 class.

Noctis Skytower
  • 21,433
  • 16
  • 79
  • 117
  • 5
    This is a clever way to inject checks for the `self.__stop` being set into the thread. Note that like most of the other solutions here, it won't actually interrupt a blocking call, since the trace function only gets called when a new local scope is entered. Also worth noting is that `sys.settrace` really meant for implementing debuggers, profiles, etc. and as such is considered an implementation detail of CPython, and is not guaranteed to exist in other Python implementations. – dano Sep 04 '14 at 21:18
  • 5
    @dano: One of the biggest problems with the `Thread2` class is that it runs code approximately ten times slower. Some people might still find this acceptable. – Noctis Skytower Sep 05 '14 at 14:20
  • 1
    +1 on this slows down the code execution considerably.. I would suggest that the author of this solution include this information in the answer. – Vishal Sep 06 '18 at 05:47
12

It is better if you don't kill a thread. A way could be to introduce a "try" block into the thread's cycle and to throw an exception when you want to stop the thread (for example a break/return/... that stops your for/while/...). I've used this on my app and it works...

JuanDeLosMuertos
  • 4,532
  • 15
  • 55
  • 87
10

I'm way late to this game, but I've been wrestling with a similar question and the following appears to both resolve the issue perfectly for me AND lets me do some basic thread state checking and cleanup when the daemonized sub-thread exits:

import threading
import time
import atexit

def do_work():

  i = 0
  @atexit.register
  def goodbye():
    print ("'CLEANLY' kill sub-thread with value: %s [THREAD: %s]" %
           (i, threading.currentThread().ident))

  while True:
    print i
    i += 1
    time.sleep(1)

t = threading.Thread(target=do_work)
t.daemon = True
t.start()

def after_timeout():
  print "KILL MAIN THREAD: %s" % threading.currentThread().ident
  raise SystemExit

threading.Timer(2, after_timeout).start()

Yields:

0
1
KILL MAIN THREAD: 140013208254208
'CLEANLY' kill sub-thread with value: 2 [THREAD: 140013674317568]
slumtrimpet
  • 3,159
  • 2
  • 31
  • 44
  • 1
    Why would raising `SystemExit` on the `after_timeout` thread do anything to the main thread (which is simply waiting on the former to exit in this example)? – Davis Herring Mar 02 '20 at 17:08
  • @DavisHerring I'm not sure what you are getting at. SystemExit kills the main thread, why do you think it WOULDNT do anything on the main thread? Without that call, the program will just continue to wait on the child thread. You could also ctrl+c or use any other means to kill the main thread but this is an example. – slumtrimpet May 01 '20 at 16:51
  • 1
    @slumtrimpet: `SystemExit` has only two special properties: it doesn’t produce a traceback (when any thread exits by throwing one), and if the *main* thread exits by throwing one it sets the exit status (while nonetheless waiting for other non-daemon threads to exit). – Davis Herring May 01 '20 at 18:17
  • -1 Main thread continued work and was not interrupted by the `SystemExit` raised from the child thread. Had to terminate the script from the terminal with `kill -9` – A Kareem Dec 25 '20 at 12:39
8

Following workaround can be used to kill a thread:

kill_threads = False

def doSomething():
    global kill_threads
    while True:
        if kill_threads:
            thread.exit()
        ......
        ......

thread.start_new_thread(doSomething, ())

This can be used even for terminating threads, whose code is written in another module, from main thread. We can declare a global variable in that module and use it to terminate thread/s spawned in that module.

I usually use this to terminate all the threads at the program exit. This might not be the perfect way to terminate thread/s but could help.

Amit Chahar
  • 2,519
  • 3
  • 18
  • 23
8

Here's yet another way to do it, but with extremely clean and simple code, that works in Python 3.7 in 2021:

import ctypes 

def kill_thread(thread):
    """
    thread: a threading.Thread object
    """
    thread_id = thread.ident
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, ctypes.py_object(SystemExit))
    if res > 1:
        ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)
        print('Exception raise failure')

Adapted from here: https://www.geeksforgeeks.org/python-different-ways-to-kill-a-thread/

serg06
  • 2,027
  • 1
  • 18
  • 26
  • 5
    If you're using Python 3.7 you must be a time traveler from 2018. If you refer to 2021, provide a test with Python 3.9. `PyThreadState_SetAsyncExc` method just does a "schedule" for an thread exit. It does **not** kill a thread especially if it's executing external C-libraries. Try to kill a `sleep(100)` with your method. It will be "killed" after 100 seconds. It's just as effective as the `while flag:` -> `flag = False` method. – sausix Jun 21 '21 at 12:42
  • Didn't work for me. No error or exception, thread keeps running as usual – Rishabh Gupta Jul 07 '23 at 05:02
7
from ctypes import *
pthread = cdll.LoadLibrary("libpthread-2.15.so")
pthread.pthread_cancel(c_ulong(t.ident))

t is your Thread object.

Read the python source (Modules/threadmodule.c and Python/thread_pthread.h) you can see the Thread.ident is an pthread_t type, so you can do anything pthread can do in python use libpthread.

vallentin
  • 23,478
  • 6
  • 59
  • 81
snyh
  • 1,225
  • 14
  • 19
  • 13
    You don't; not on Windows and not on Linux either. Reason: The thread in question might hold the GIL while you're doing this (Python releases the GIL when you call into C). If it does, your program will instantly deadlock. Even if it doesn't, finally: blocks will not be executed etc., so this is a very unsafe idea. – Matthias Urlichs Jun 22 '14 at 16:00
  • Tried this within ipython, the whole ipython process just hangs. – user4918159 May 04 '23 at 21:07
4

One thing I want to add is that if you read official documentation in threading lib Python, it's recommended to avoid use of "demonic" threads, when you don't want threads end abruptly, with the flag that Paolo Rovelli mentioned.

From official documentation:

Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signaling mechanism such as an Event.

I think that creating daemonic threads depends of your application, but in general (and in my opinion) it's better to avoid killing them or making them daemonic. In multiprocessing you can use is_alive() to check process status and "terminate" for finish them (Also you avoid GIL problems). But you can find more problems, sometimes, when you execute your code in Windows.

And always remember that if you have "live threads", the Python interpreter will be running for wait them. (Because of this daemonic can help you if don't matter abruptly ends).

Community
  • 1
  • 1
Chema
  • 91
  • 3
  • @Tshepang It means that if there are any running non-daemonic threads in your application, the Python interpreter will continue running until **_all_ non-daemon** threads are **done**. If you don't care if the thread(s) end when the program terminates, then making them daemon can be of use. – Tom Myddeltyn May 06 '16 at 16:17
4

There is a library built for this purpose, stopit. Although some of the same cautions listed herein still apply, at least this library presents a regular, repeatable technique for achieving the stated goal.

Jason R. Coombs
  • 41,115
  • 10
  • 83
  • 93
2

While it's rather old, this might be a handy solution for some:

A little module that extends the threading's module functionality -- allows one thread to raise exceptions in the context of another thread. By raising SystemExit, you can finally kill python threads.

import threading
import ctypes     

def _async_raise(tid, excobj):
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(excobj))
    if res == 0:
        raise ValueError("nonexistent 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(tid, 0)
        raise SystemError("PyThreadState_SetAsyncExc failed")

class Thread(threading.Thread):
    def raise_exc(self, excobj):
        assert self.isAlive(), "thread must be started"
        for tid, tobj in threading._active.items():
            if tobj is self:
                _async_raise(tid, excobj)
                return

        # the thread was alive when we entered the loop, but was not found 
        # in the dict, hence it must have been already terminated. should we raise
        # an exception here? silently ignore?

    def terminate(self):
        # must raise the SystemExit type, instead of a SystemExit() instance
        # due to a bug in PyThreadState_SetAsyncExc
        self.raise_exc(SystemExit)

So, it allows a "thread to raise exceptions in the context of another thread" and in this way, the terminated thread can handle the termination without regularly checking an abort flag.

However, according to its original source, there are some issues with this code.

  • The exception will be raised only when executing python bytecode. If your thread calls a native/built-in blocking function, the exception will be raised only when execution returns to the python code.
    • There is also an issue if the built-in function internally calls PyErr_Clear(), which would effectively cancel your pending exception. You can try to raise it again.
  • Only exception types can be raised safely. Exception instances are likely to cause unexpected behavior, and are thus restricted.
  • I asked to expose this function in the built-in thread module, but since ctypes has become a standard library (as of 2.5), and this
    feature is not likely to be implementation-agnostic, it may be kept
    unexposed.
wp78de
  • 18,207
  • 7
  • 43
  • 71
2

Asuming, that you want to have multiple threads of the same function, this is IMHO the easiest implementation to stop one by id:

import time
from threading import Thread

def doit(id=0):
    doit.stop=0
    print("start id:%d"%id)
    while 1:
        time.sleep(1)
        print(".")
        if doit.stop==id:
            doit.stop=0
            break
    print("end thread %d"%id)

t5=Thread(target=doit, args=(5,))
t6=Thread(target=doit, args=(6,))

t5.start() ; t6.start()
time.sleep(2)
doit.stop =5  #kill t5
time.sleep(2)
doit.stop =6  #kill t6

The nice thing is here, you can have multiple of same and different functions, and stop them all by functionname.stop

If you want to have only one thread of the function then you don't need to remember the id. Just stop, if doit.stop > 0.

rundekugel
  • 1,118
  • 1
  • 10
  • 23
2

Just to build up on @SCB's idea (which was exactly what I needed) to create a KillableThread subclass with a customized function:

from threading import Thread, Event

class KillableThread(Thread):
    def __init__(self, sleep_interval=1, target=None, name=None, args=(), kwargs={}):
        super().__init__(None, target, name, args, kwargs)
        self._kill = Event()
        self._interval = sleep_interval
        print(self._target)

    def run(self):
        while True:
            # Call custom function with arguments
            self._target(*self._args)

            # If no kill signal is set, sleep for the interval,
            # If kill signal comes in while sleeping, immediately
            #  wake up and handle
            is_killed = self._kill.wait(self._interval)
            if is_killed:
                break

        print("Killing Thread")

    def kill(self):
        self._kill.set()

if __name__ == '__main__':

    def print_msg(msg):
        print(msg)

    t = KillableThread(10, print_msg, args=("hello world"))
    t.start()
    time.sleep(6)
    print("About to kill thread")
    t.kill()

Naturally, like with @SBC, the thread doesn't wait to run a new loop to stop. In this example, you would see the "Killing Thread" message printed right after the "About to kill thread" instead of waiting for 4 more seconds for the thread to complete (since we have slept for 6 seconds already).

Second argument in KillableThread constructor is your custom function (print_msg here). Args argument are the arguments that will be used when calling the function (("hello world")) here.

Ouroborus
  • 16,237
  • 4
  • 39
  • 62
Tim Meehan
  • 160
  • 2
  • 8
2

Python version: 3.8

Using daemon thread to execute what we wanted, if we want to daemon thread be terminated, all we need is making parent thread exit, then system will terminate daemon thread which parent thread created.

Also support coroutine and coroutine function.

def main():
    start_time = time.perf_counter()
    t1 = ExitThread(time.sleep, (10,), debug=False)
    t1.start()
    time.sleep(0.5)
    t1.exit()
    try:
        print(t1.result_future.result())
    except concurrent.futures.CancelledError:
        pass
    end_time = time.perf_counter()
    print(f"time cost {end_time - start_time:0.2f}")

below is ExitThread source code

import concurrent.futures
import threading
import typing
import asyncio


class _WorkItem(object):
    """ concurrent\futures\thread.py

    """

    def __init__(self, future, fn, args, kwargs, *, debug=None):
        self._debug = debug
        self.future = future
        self.fn = fn
        self.args = args
        self.kwargs = kwargs

    def run(self):
        if self._debug:
            print("ExitThread._WorkItem run")
        if not self.future.set_running_or_notify_cancel():
            return

        try:
            coroutine = None
            if asyncio.iscoroutinefunction(self.fn):
                coroutine = self.fn(*self.args, **self.kwargs)
            elif asyncio.iscoroutine(self.fn):
                coroutine = self.fn
            if coroutine is None:
                result = self.fn(*self.args, **self.kwargs)
            else:
                result = asyncio.run(coroutine)
            if self._debug:
                print("_WorkItem done")
        except BaseException as exc:
            self.future.set_exception(exc)
            # Break a reference cycle with the exception 'exc'
            self = None
        else:
            self.future.set_result(result)


class ExitThread:
    """ Like a stoppable thread

    Using coroutine for target then exit before running may cause RuntimeWarning.

    """

    def __init__(self, target: typing.Union[typing.Coroutine, typing.Callable] = None
                 , args=(), kwargs={}, *, daemon=None, debug=None):
        #
        self._debug = debug
        self._parent_thread = threading.Thread(target=self._parent_thread_run, name="ExitThread_parent_thread"
                                               , daemon=daemon)
        self._child_daemon_thread = None
        self.result_future = concurrent.futures.Future()
        self._workItem = _WorkItem(self.result_future, target, args, kwargs, debug=debug)
        self._parent_thread_exit_lock = threading.Lock()
        self._parent_thread_exit_lock.acquire()
        self._parent_thread_exit_lock_released = False  # When done it will be True
        self._started = False
        self._exited = False
        self.result_future.add_done_callback(self._release_parent_thread_exit_lock)

    def _parent_thread_run(self):
        self._child_daemon_thread = threading.Thread(target=self._child_daemon_thread_run
                                                     , name="ExitThread_child_daemon_thread"
                                                     , daemon=True)
        self._child_daemon_thread.start()
        # Block manager thread
        self._parent_thread_exit_lock.acquire()
        self._parent_thread_exit_lock.release()
        if self._debug:
            print("ExitThread._parent_thread_run exit")

    def _release_parent_thread_exit_lock(self, _future):
        if self._debug:
            print(f"ExitThread._release_parent_thread_exit_lock {self._parent_thread_exit_lock_released} {_future}")
        if not self._parent_thread_exit_lock_released:
            self._parent_thread_exit_lock_released = True
            self._parent_thread_exit_lock.release()

    def _child_daemon_thread_run(self):
        self._workItem.run()

    def start(self):
        if self._debug:
            print(f"ExitThread.start {self._started}")
        if not self._started:
            self._started = True
            self._parent_thread.start()

    def exit(self):
        if self._debug:
            print(f"ExitThread.exit exited: {self._exited} lock_released: {self._parent_thread_exit_lock_released}")
        if self._parent_thread_exit_lock_released:
            return
        if not self._exited:
            self._exited = True
            if not self.result_future.cancel():
                if self.result_future.running():
                    self.result_future.set_exception(concurrent.futures.CancelledError())
林奕忠
  • 751
  • 8
  • 12
1

As mentioned in @Kozyarchuk's answer, installing trace works. Since this answer contained no code, here is a working ready-to-use example:

import sys, threading, time 

class TraceThread(threading.Thread): 
    def __init__(self, *args, **keywords): 
        threading.Thread.__init__(self, *args, **keywords) 
        self.killed = False
    def start(self): 
        self._run = self.run 
        self.run = self.settrace_and_run
        threading.Thread.start(self) 
    def settrace_and_run(self): 
        sys.settrace(self.globaltrace) 
        self._run()
    def globaltrace(self, frame, event, arg): 
        return self.localtrace if event == 'call' else None
    def localtrace(self, frame, event, arg): 
        if self.killed and event == 'line': 
            raise SystemExit() 
        return self.localtrace 

def f(): 
    while True: 
        print('1') 
        time.sleep(2)
        print('2') 
        time.sleep(2)
        print('3') 
        time.sleep(2)

t = TraceThread(target=f) 
t.start() 
time.sleep(2.5) 
t.killed = True

It stops after having printed 1 and 2. 3 is not printed.

Basj
  • 41,386
  • 99
  • 383
  • 673
1

An alternative is to use signal.pthread_kill to send a stop signal.

from signal import pthread_kill, SIGTSTP
from threading import Thread
from itertools import count
from time import sleep

def target():
    for num in count():
        print(num)
        sleep(1)

thread = Thread(target=target)
thread.start()
sleep(5)
pthread_kill(thread.ident, SIGTSTP)

result

0
1
2
3
4

[14]+  Stopped
reubano
  • 5,087
  • 1
  • 42
  • 41
0

If you really need the ability to kill a sub-task, use an alternate implementation. multiprocessing and gevent both support indiscriminately killing a "thread".

Python's threading does not support cancellation. Do not even try. Your code is very likely to deadlock, corrupt or leak memory, or have other unintended "interesting" hard-to-debug effects which happen rarely and nondeterministically.

Matthias Urlichs
  • 2,301
  • 19
  • 29
  • 2
    … and yes, I know that both are not strictly "threading", but they both work if your code fits (or can be made to fit) their model. – Matthias Urlichs Sep 20 '15 at 15:08
0

Pieter Hintjens -- one of the founders of the ØMQ-project -- says, using ØMQ and avoiding synchronization primitives like locks, mutexes, events etc., is the sanest and securest way to write multi-threaded programs:

http://zguide.zeromq.org/py:all#Multithreading-with-ZeroMQ

This includes telling a child thread, that it should cancel its work. This would be done by equipping the thread with a ØMQ-socket and polling on that socket for a message saying that it should cancel.

The link also provides an example on multi-threaded python code with ØMQ.

kernstock
  • 224
  • 2
  • 10
-1

This seems to work with pywin32 on windows 7

my_thread = threading.Thread()
my_thread.start()
my_thread._Thread__stop()
zzart
  • 11,207
  • 5
  • 52
  • 47
-1

You can execute your command in a process and then kill it using the process id. I needed to sync between two thread one of which doesn’t return by itself.

processIds = []

def executeRecord(command):
    print(command)

    process = subprocess.Popen(command, stdout=subprocess.PIPE)
    processIds.append(process.pid)
    print(processIds[0])

    #Command that doesn't return by itself
    process.stdout.read().decode("utf-8")
    return;


def recordThread(command, timeOut):

    thread = Thread(target=executeRecord, args=(command,))
    thread.start()
    thread.join(timeOut)

    os.kill(processIds.pop(), signal.SIGINT)

    return;
user1942887
  • 94
  • 1
  • 5
-2

Start the sub thread with setDaemon(True).

def bootstrap(_filename):
    mb = ModelBootstrap(filename=_filename) # Has many Daemon threads. All get stopped automatically when main thread is stopped.

t = threading.Thread(target=bootstrap,args=('models.conf',))
t.setDaemon(False)

while True:
    t.start()
    time.sleep(10) # I am just allowing the sub-thread to run for 10 sec. You can listen on an event to stop execution.
    print('Thread stopped')
    break
Sud
  • 183
  • 1
  • 7
-2

This is a bad answer, see the comments

Here's how to do it:

from threading import *

...

for thread in enumerate():
    if thread.isAlive():
        try:
            thread._Thread__stop()
        except:
            print(str(thread.getName()) + ' could not be terminated'))

Give it a few seconds then your thread should be stopped. Check also the thread._Thread__delete() method.

I'd recommend a thread.quit() method for convenience. For example if you have a socket in your thread, I'd recommend creating a quit() method in your socket-handle class, terminate the socket, then run a thread._Thread__stop() inside of your quit().

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
DoXiD
  • 285
  • 2
  • 2
  • 12
    More details on "this doesn't really stop a thread" would be helpful. – 2371 Dec 27 '11 at 22:40
  • 19
    Basically, calling the _Thread__stop method has no effect apart from telling Python that the thread is stopped. It can actually continue running. See https://gist.github.com/2787191 for an example. – Bluehorn May 25 '12 at 10:26
  • 35
    This is plain wrong. `_Thread__stop()` merely _marks a thread as stopped_, it does not actually stop the thread! Never do this. [Have a read](http://eli.thegreenplace.net/2011/08/22/how-not-to-set-a-timeout-on-a-computation-in-python/). – dotancohen Jul 21 '13 at 07:16
-2

The most simple way is this:

from threading import Thread
from time import sleep

def do_something():
    global thread_work
    while thread_work:
        print('doing something')
        sleep(5)
    print('Thread stopped')

thread_work = True
Thread(target=do_something).start()
sleep(5)
thread_work = False