Ist es möglich, einen laufenden Thread zu beenden, ohne irgendwelche Flags/Semaphoren/etc. zu setzen/zu überprüfen?
Antworten
Zu viele Anzeigen?from ctypes import *
pthread = cdll.LoadLibrary("libpthread-2.15.so")
pthread.pthread_cancel(c_ulong(t.ident))
t ist Ihr Thread
Objekt.
Lesen Sie den Python-Quelltext ( Modules/threadmodule.c
y Python/thread_pthread.h
) können Sie die Thread.ident
ist ein pthread_t
Typ, so dass Sie alles tun können pthread
in Python tun können, verwenden Sie libpthread
.
Eine Sache, die ich hinzufügen möchte, ist, dass, wenn Sie die offizielle Dokumentation in threading lib Python Es wird empfohlen, die Verwendung von "dämonischen" Fäden zu vermeiden, wenn man nicht will, dass Fäden abrupt enden, mit dem Hinweis, dass Paolo Rovelli erwähnt .
Aus der offiziellen Dokumentation:
Daemon-Threads werden beim Herunterfahren abrupt beendet. Ihre Ressourcen (wie offene Dateien, Datenbanktransaktionen usw.) werden möglicherweise nicht ordnungsgemäß freigegeben. Wenn Sie möchten, dass Ihre Threads ordnungsgemäß beendet werden, machen Sie sie zu nicht-dämonischen Threads und verwenden Sie einen geeigneten Signalisierungsmechanismus wie z. B. ein Ereignis.
Ich denke, dass das Erstellen von daemonischen Threads von Ihrer Anwendung abhaengt, aber im Allgemeinen (und meiner Meinung nach) ist es besser, sie nicht zu toeten oder sie daemonisch zu machen. Im Multiprocessing können Sie Folgendes verwenden is_alive()
um den Status von Prozessen zu überprüfen und sie mit "terminate" zu beenden (auch um GIL-Probleme zu vermeiden). Aber Sie können mehr Probleme finden, manchmal, wenn Sie Ihren Code in Windows ausführen.
Und denken Sie immer daran, dass, wenn Sie "Live-Threads" haben, der Python-Interpreter läuft, um sie zu warten. (Wegen dieser daemonischen kann Ihnen helfen, wenn don't Materie abrupt endet).
Zu diesem Zweck wurde eine Bibliothek eingerichtet, stopit . Auch wenn einige der hier aufgeführten Vorsichtsmaßnahmen nach wie vor gelten, bietet diese Bibliothek zumindest eine regelmäßige, wiederholbare Technik, um das erklärte Ziel zu erreichen.
Nur um auf @SCBs Idee aufzubauen (die genau das war, was ich brauchte), eine KillableThread-Unterklasse mit einer angepassten Funktion zu erstellen:
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()
Wie bei @SBC wartet der Thread natürlich nicht darauf, dass eine neue Schleife läuft, um anzuhalten. In diesem Beispiel würden Sie die Meldung "Killing Thread" direkt nach der Meldung "About to kill thread" sehen, anstatt 4 weitere Sekunden auf den Abschluss des Threads zu warten (da wir bereits 6 Sekunden geschlafen haben).
Das zweite Argument im KillableThread-Konstruktor ist Ihre eigene Funktion (hier print_msg). Args-Argument sind die Argumente, die beim Aufruf der Funktion (("hello world")) hier verwendet werden.
Eine Alternative ist die Verwendung von signal.pthread_kill
um ein Stoppsignal zu senden.
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)
Ergebnis
0
1
2
3
4
[14]+ Stopped