Can you kill a thread in Python?

Asked

Viewed 1,948 times

1

Is there any way to stop a python thread? And it’s a bad practice to do that?

  • question and answer copied and pasted from the English OS would be at least fair to give credit to those who asked/answered....

1 answer

1


It is a bad practice to abruptly stop a thread in any language.

Let’s think The thread has some critical feature that needs to be closed properly. The thread has other threads that must be stopped along with this thread.

The best way to deal with this if you can, (if you’re managing your own threads) is to have a flag exit_request that each thread checks regularly to see if it’s time to close.

Let’s go to an example:

import threading

class StoppableThread(threading.Thread):
    """Thread class com metodo de stop(). A thread precisa checar 
    regularmente pela condição de stopped() ."""

    def __init__(self):
        super(StoppableThread, self).__init__()
        self._stop = threading.Event()

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

    def stopped(self):
        return self._stop.isSet()

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 and you want to stop it.

The following example allows (with some restrictions) to throw an exception on a Python thread:

def _async_raise(tid, exctype):
    '''Lanca uma excecao na threads com id tid'''
    if not inspect.isclass(exctype):
        raise TypeError("Somente tipos podem ser lancados (nao instancias)")
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
                                                  ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("thread com invalido id")
    elif res != 1:
        # "Se lancar um numero maior que um, eh um problema,
        # e voce deveria chamar novamente com exc=NULL para reverter o efeito"
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
        raise SystemError("PyThreadState_SetAsyncExc falhou")

class ThreadWithExc(threading.Thread):
    def _get_my_tid(self):
        if not self.isAlive():
            raise threading.ThreadError("the thread is not active")

        if hasattr(self, "_thread_id"):
            return self._thread_id

        for tid, tobj in threading._active.items():
            if tobj is self:
                self._thread_id = tid
                return tid

        # TODO: em python 2.6, existe uma forma mais simples : self.ident

        raise AssertionError("nao pode determinar as threads com id")

    def raiseExc(self, exctype):
        _async_raise( self._get_my_tid(), exctype )

As noted, this is not perfect, because if the thread is busy outside the Python interpreter, it will not catch the interruption.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.