Czy jest jakiś sposób na zabicie wątku w Pythonie?

Czy można zakończyć uruchomiony wątek bez ustawiania / sprawdzania FLAG / semaforów / itd.?

Author: igaurav, 2008-11-27

24 answers

W Pythonie i w każdym języku jest to na ogół zły wzór, aby nagle zabić wątek. Pomyśl o następujących przypadkach:

  • wątek przechowuje krytyczny zasób, który musi być poprawnie zamknięty
  • wątek stworzył kilka innych wątków, które również muszą zostać zabite.

Dobrym sposobem obsługi tego, jeśli możesz sobie na to pozwolić (jeśli zarządzasz własnymi wątkami) jest posiadanie znacznika exit_request, który każdy wątek sprawdza regularny interwał, aby sprawdzić, czy jest czas na wyjście.

Na przykład:

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):
        super(StoppableThread, self).__init__()
        self._stop_event = threading.Event()

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

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

W tym kodzie należy wywołać stop () w wątku, gdy ma się zakończyć, i poczekać, aż wątek zakończy się poprawnie za pomocą join (). Wątek powinien sprawdzać znacznik stop w regularnych odstępach czasu.

Są jednak przypadki, kiedy naprawdę trzeba zabić wątek. Przykładem jest zawijanie zewnętrznej biblioteki, która jest zajęta przez długie połączenia i chcesz ją przerwać.

Poniższy kod pozwala (z niektóre ograniczenia), aby podnieść wyjątek w wątku Pythona:

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 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 excpetion in the context of the
        thread represented by this instance.
        """
        _async_raise( self._get_my_tid(), exctype )

(na podstawie Killable Threads by Tomer Filiba. Cytat o zwracanej wartości PyThreadState_SetAsyncExc wydaje się pochodzić ze starej wersji Pythona .)

Jak wspomniano w dokumentacji, nie jest to magiczna kula, ponieważ jeśli wątek jest zajęty poza interpreterem Pythona, nie wychwytuje przerwania.

Dobrym wzorcem użycia tego kodu jest to, aby wątek złapał konkretny wyjątek i przeprowadzić sprzątanie. W ten sposób możesz przerwać zadanie i nadal mieć odpowiednie sprzątanie.

 546
Author: Philippe F,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-14 03:56:33

Nie ma oficjalnego API, aby to zrobić, nie.

Musisz użyć platform API, aby zabić wątek, np. pthread_kill, lub TerminateThread. Możesz uzyskać dostęp do takiego API np. przez pythonwin lub przez ctypes.

Zauważ, że jest to z natury niebezpieczne. Prawdopodobnie doprowadzi to do nieoczyszczalnych śmieci (od lokalnych zmiennych ramek stosu, które stają się śmieciami) i może prowadzić do blokad, jeśli wątek zabity ma GIL w momencie jego zabicia.

 99
Author: Martin v. Löwis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-27 15:08:07

A multiprocessing.Process can p.terminate()

W przypadkach, gdy chcę zabić wątek, ale nie chcę używać FLAG/blokad/sygnałów/semaforów/zdarzeń/cokolwiek, promuję wątki do pełnych procesów. Dla kodu, który wykorzystuje tylko kilka wątków, narzut nie jest taki zły.

Np. jest to przydatne do łatwego zakończenia "wątków" pomocniczych, które wykonują blokowanie We / Wy

Konwersja jest trywialna: w powiązanym kodzie Zamień wszystkie threading.Thread na multiprocessing.Process i wszystkie queue.Queue na multiprocessing.Queue i dodaj wymagane wywołania p.terminate() do procesu rodzica, który chce zabić swoje dziecko p

Python doc

 64
Author: cfi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-13 09:38:20

Jeśli próbujesz zakończyć cały program, możesz ustawić wątek jako "daemon". Zobacz też Wątek.daemon

 57
Author: schettino72,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-18 15:54:53

Nigdy nie należy siłą zabijać wątku bez współpracy z nim.

Zabicie wątku usuwa wszelkie gwarancje, że try/finally blokuje ustawione tak, że można pozostawić zablokowane blokady, otwarte pliki itp.

Jedyny raz, kiedy można argumentować, że wymuszone zabijanie wątków jest dobrym pomysłem, to szybkie zabicie programu, ale nigdy pojedynczych wątków.

 29
Author: Lasse Vågsæther Karlsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-27 14:58:49

Jest to oparte na thread2 -- killable threads (Python recipe)

Musisz wywołać metodę PyThreadState_SetasyncExc(), która jest dostępna tylko przez ctypes.

To zostało przetestowane tylko na Pythonie 2.7.3, ale prawdopodobnie będzie działać z innymi ostatnimi 2.x releases.

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")
 28
Author: Johan Dahlin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-28 08:56:28

Jak wspomnieli inni, normą jest ustawienie flagi stop. Dla czegoś lekkiego (bez podklasowania wątku, bez zmiennej globalnej), lambda callback jest opcją. (Zwróć uwagę na nawiasy w 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()

Zastąpienie print() funkcją pr(), która zawsze spłukuje (sys.stdout.flush()) może poprawić precyzję wyjścia powłoki.

(testowane tylko na Windows / Eclipse / Python3.3)

 25
Author: Jon Coombs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-03 00:07:06

W Pythonie, po prostu nie można zabić wątku bezpośrednio.

Jeśli naprawdę nie musisz mieć wątku (!), co można zrobić, zamiast korzystać z threading package , jest użycie multiprocessing package . Tutaj, aby zabić proces, możesz po prostu wywołać metodę:

yourProcess.terminate()  # kill the process!

Python zabije twój proces (w Unixie przez sygnał SIGTERM, podczas gdy w Windows przez wywołanie TerminateProcess()). Zwróć uwagę, aby używać go podczas korzystania z kolejki albo Rura! (może uszkodzić dane w kolejce / potoku)

Zauważ, że multiprocessing.Event i multiprocessing.Semaphore działają dokładnie w ten sam sposób, odpowiednio threading.Event i threading.Semaphore. W rzeczywistości pierwsze są klonami tych ostatnich.

Jeśli naprawdę potrzebujesz użyć wątku, nie ma sposobu, aby go zabić bezpośrednio. Możesz jednak użyć "daemon thread" . W Pythonie wątek może być oznaczony jako daemon :

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

Główny program zakończy działanie, gdy nie / align = "left" / Innymi słowy, gdy twój główny wątek (który jest oczywiście nie-demonem) zakończy swoje operacje, program zakończy działanie, nawet jeśli nadal działają niektóre wątki demona.

Zauważ, że przed wywołaniem metody start() konieczne jest ustawienie wątku jako daemon!

Oczywiście możesz i powinieneś używać daemon nawet z multiprocessing. W tym przypadku, gdy główny proces zakończy działanie, próbuje zakończyć wszystkie swoje demoniczne dziecko procesy.

Na koniec proszę zauważyć, że sys.exit() i os.kill() nie są wyborami.

 18
Author: Paolo Rovelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-24 02:16:31

Możesz zabić wątek, instalując trace w wątku, który zakończy wątek. Zobacz załączony link do jednej z możliwych realizacji.

Zabij wątek w Pythonie

 13
Author: Kozyarchuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-14 01:40:37

Jest lepiej, jeśli nie zabijasz wątku. Sposobem może być wprowadzenie bloku" try " do cyklu wątku i rzucenie wyjątku, gdy chcesz zatrzymać wątek (na przykład break/return/... to zatrzymuje twoje na / chwilę/...). Użyłem tego w mojej aplikacji i działa...

 9
Author: Giancarlo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-27 15:12:07

Jest zdecydowanie możliwe zaimplementowanie metody Thread.stop, Jak pokazano w poniższym przykładowym kodzie:

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()

Klasa Thread3 wydaje się uruchamiać kod o około 33% szybciej niż klasa Thread2.

 7
Author: Noctis Skytower,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-13 15:37:29
from ctypes import *
pthread = cdll.LoadLibrary("libpthread-2.15.so")
pthread.pthread_cancel(c_ulong(t.ident))

T jest Twoim Thread obiektem.

Przeczytaj źródło Pythona (Modules/threadmodule.c i Python/thread_pthread.h) możesz zobaczyć Thread.ident jest typem pthread_t, więc możesz zrobić wszystko pthread może zrobić w Pythonie używać libpthread.

 7
Author: snyh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-24 02:16:42

Chcę jeszcze dodać, że jeśli czytasz oficjalną dokumentację w threading lib Python , zaleca się unikać używania "demonicznych" wątków, gdy nie chcesz, aby wątki kończyły się nagle, z flagą, o której wspomniał Paolo Rovelli .

Z oficjalnej dokumentacji:

Wątki demona są nagle zatrzymywane podczas zamykania. Ich zasobów (takich jak otwarte pliki, transakcje bazodanowe itp.) może nie być prawidłowo zwolniony. Jeśli chcesz, aby twoje wątki się zatrzymały z wdziękiem uczyń je nie daemonicznymi i użyj odpowiedniego mechanizmu sygnalizacyjnego, takiego jak Zdarzenie.

Myślę, że tworzenie wątków daemonicznych zależy od twojej aplikacji, ale ogólnie (i moim zdaniem) lepiej unikać ich zabijania lub robienia z nich daemonicznych. W multiprocessingu możesz użyć is_alive(), aby sprawdzić status procesu i "zakończyć", aby je zakończyć(również unikasz problemów z GIL). Ale czasami możesz znaleźć więcej problemów podczas wykonywania kodu w systemie Windows.

Oraz zawsze pamiętaj, że jeśli masz "żywe wątki", interpreter Pythona będzie uruchomiony na ich oczekiwanie. (Z powodu tego daemonic może pomóc, jeśli nie ma znaczenia nagle się kończy).

 4
Author: Chema,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:41

Jestem spóźniony do tej gry, ale zmagałem się z podobnym pytaniem i następujące wydaje się, że oba rozwiązują problem idealnie dla mnie i pozwalają mi zrobić podstawowe sprawdzanie stanu wątku i czyszczenie, gdy daemonized sub-thread zakończy działanie: {]}

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()

0
1
KILL MAIN THREAD: 140013208254208
'CLEANLY' kill sub-thread with value: 2 [THREAD: 140013674317568]
 2
Author: slumtrimpet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-22 18:37:59

To zła odpowiedź, Zobacz komentarze

Oto Jak to zrobić:

from threading import *

...

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

Daj mu kilka sekund, a Twój wątek powinien zostać zatrzymany. Sprawdź również metodę thread._Thread__delete().

Polecam metodę thread.quit()dla wygody. Na przykład, jeśli masz gniazdo w wątku, polecam utworzenie metody quit() w klasie socket-handle, zakończenie gniazda, a następnie uruchomienie thread._Thread__stop() wewnątrz twojego quit().
 1
Author: DoXiD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-30 02:11:07

Uruchom wątek podrzędny za pomocą 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
 0
Author: Sud,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-17 20:13:43

Chociaż jest dość stary, to może być dla niektórych przydatne rozwiązanie:

Mały moduł rozszerzający funkcjonalność modułu wątku -- pozwala jednemu wątkowi zgłaszać wyjątki w kontekście innego nić. Podnosząc SystemExit, możesz w końcu zabić wątki Pythona.

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)

Pozwala więc "wątkowi zgłaszać wyjątki w kontekście innego wątku" i w ten sposób zakończony wątek może obsłużyć zakończenie bez regularnego sprawdzania flaga przerwania.

Jednak, zgodnie z jego oryginalnym źródłem , są pewne problemy z tym kodem.

  • wyjątek zostanie wywołany tylko podczas wykonywania bajtowego kodu Pythona. Jeśli Twój wątek wywoła natywną / wbudowaną funkcję blokowania, wyjątek zostanie podniesiony tylko wtedy, gdy wykonanie powróci do Pythona kod.
    • istnieje również problem, jeśli wbudowana funkcja wewnętrznie wywołuje PyErr_Clear (), co skutecznie anuluje Twoje wyjątek oczekujący. Możesz spróbować podnieść go ponownie.
  • tylko typy WYJĄTKÓW mogą być podniesione bezpiecznie. Wyjątki mogą powodować nieoczekiwane zachowanie, a zatem są ograniczone.
[18]}poprosiłem o udostępnienie tej funkcji we wbudowanym module wątku, ale ponieważ ctypes stał się standardową biblioteką (od 2.5), A to
funkcja nie może być implementowana-agnostyczna, może być przechowywana
nienaświetlone.
 0
Author: wp78de,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-24 07:15:56

Pieter Hintjens -- jeden z założycieli ØMQ -project -- mówi, używając ØMQ i unikając prymitywów synchronizacji, takich jak zamki, muteksy, zdarzenia itp., jest najbezpieczniejszym i najbezpieczniejszym sposobem pisania programów wielowątkowych:

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

Obejmuje to poinformowanie wątku podrzędnego, że powinien on anulować jego pracę. Można to zrobić poprzez wyposażenie wątku w gniazdo ØMQ i wyszukanie na tym gnieździe wiadomości mówiąc, że powinno się odwołać.

Link dostarcza również przykład wielowątkowego kodu Pythona z ØMQ.

 0
Author: paulkernstock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-09 11:18:10

Następujące obejście może być użyte do zabicia wątku:

kill_threads = False

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

thread.start_new_thread(doSomething, ())

Może być używany nawet do kończenia wątków, których kod jest zapisany w innym module, z głównego wątku. Możemy zadeklarować zmienną globalną w tym module i użyć jej do zakończenia wątków / s zrodzonych w tym module.

Zwykle używam tego do zakończenia wszystkich wątków przy wyjściu programu. Może to nie jest idealny sposób na zakończenie wątków, ale może pomóc.

 0
Author: Amit Chahar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-14 21:59:07

Jeśli jawnie wywołujesz time.sleep() jako część swojego wątku (powiedzmy, że używasz jakiegoś zewnętrznego serwisu), ulepszeniem metody jest użycie timeoutu w metodzie event'S wait() gdziekolwiek sleep()

Na przykład:

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()

Następnie uruchomić go

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

Zaletą używania wait() zamiast sleep()ing i regularnego sprawdzania zdarzenia jest to, że można programować w dłuższych odstępach czasu snu, wątek jest zatrzymywany niemal natychmiast (gdy w przeciwnym razie byłby sleep() ing) i moim zdaniem kod do obsługi exit jest znacznie prostszy.

 0
Author: SCB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-17 12:05:19

Istnieje Biblioteka zbudowana w tym celu, stopit . Chociaż niektóre z tych samych ostrzeżeń wymienionych w niniejszym dokumencie nadal obowiązują, przynajmniej ta biblioteka prezentuje regularną, powtarzalną technikę osiągnięcia określonego celu.

 0
Author: Jason R. Coombs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-23 23:53:12

Wygląda na to, że działa z pywin32 na windows 7

my_thread = threading.Thread()
my_thread.start()
my_thread._Thread__stop()
 -1
Author: zzart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-29 10:59:06

Możesz wykonać polecenie w procesie, a następnie go zabić, używając identyfikatora procesu. Musiałem zsynchronizować dwa wątki, z których jeden nie wraca sam.

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;
 -1
Author: user1942887,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-14 19:01:09

Jeśli naprawdę potrzebujesz możliwości zabicia podrzędnego zadania, użyj alternatywnej implementacji. multiprocessing i gevent oba wspierają bezkrytycznie zabijanie "wątku".

Wątek Pythona nie obsługuje anulowania. Nawet nie próbuj. Twój kod może zablokować, uszkodzić lub wyciekać pamięć lub mieć inne niezamierzone "interesujące" trudne do debugowania efekty, które zdarzają się rzadko i nieoznaczoności.

 -2
Author: Matthias Urlichs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-17 06:21:26