Programm "Ich kann nicht aufhören ..." Ich "Bitte hör auf"
Dieser Artikel ist der Artikel zum 7. Tag des N High School Adventskalenders 2019. Ich bin derzeit im zweiten Jahr meines zweiten Jahres (es gab viele Dinge, als ich wechselte) und besuche einen Schulkurs. Ich bin sehr dankbar, dass die N High School sein eigenes Projekt in der Programmierzeit durchführen kann, solange er die wesentlichen Aufgaben erledigt.
In diesem Artikel werde ich über die Probleme schreiben, mit denen ich beim Erstellen von Discord- und Twitter-Bots in Python konfrontiert war. Bitte weisen Sie auf Fehler hin.
Als ich versuchte, ein Programm mit Python-Threading mit Tastaturunterbrechung (Strg + C) zu stoppen, wurde es aus irgendeinem Grund nicht sofort gestoppt.
Bei weiteren Untersuchungen hörte sys.exit ()
nicht auf.
OS: Windows 10 Home Runtime: Python 3.8.0
Vorerst habe ich beschlossen, Code zur Überprüfung mithilfe von Threading zu schreiben.
import threading
import time
#Funktionsdefinition
def a():
for i in range(5):
time.sleep(1)
print("A" + str(i))
def b():
time.sleep(0.5)
for j in range(5):
time.sleep(1)
print("B" + str(j))
#Thread-Objekterstellung
t1 = threading.Thread(target=a)
t2 = threading.Thread(target=b)
#Lauf
t1.start()
t2.start()
#Warten Sie bis zum Ende
t1.join()
t2.join()
print("Finish")
Wie erwartet sieht die Ausgabe folgendermaßen aus: Fertig stellen wurde gleichzeitig mit B4 angezeigt.
A0
B0
A1
B1
A2
B2
A3
B3
A4
B4
Finish
Lassen Sie uns dies nun in eine Endlosschleife umwandeln.
import threading
import time
#Funktionsdefinition
def a():
c=1
while True:
time.sleep(1)
print("A" + str(c))
c+=1
def b():
k=1
time.sleep(0.5)
while True:
time.sleep(1)
print("B" + str(k))
k+=1
#Thread-Objekterstellung
t1 = threading.Thread(target=a)
t2 = threading.Thread(target=b)
#Lauf
t1.start()
t2.start()
#Warten Sie bis zum Ende
t1.join()
t2.join()
Die Ausgabe ist wie folgt.
A1
B1
A2
B2
A3
B3
^CTraceback (most recent call last):
File "***********.py", line 28, in <module>
t1.join()
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 1011, in join
self._wait_for_tstate_lock()
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 1027, in _wait_for_tstate_lock
elif lock.acquire(block, timeout):
KeyboardInterrupt
A4
B4
A5
B5
A6
B6
^CException ignored in: <module 'threading' from '/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py'>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 1388, in _shutdown
lock.acquire()
KeyboardInterrupt:
Aus irgendeinem Grund hörte es beim ersten Keyboard Interrupt nicht auf. Diesmal habe ich es zweimal gemacht und es hat aufgehört, aber ich möchte es nach Möglichkeit vermeiden.
Sie müssen nicht "bis zum Ende warten". Mit anderen Worten, löschen Sie einfach **. Join ()
.
Wenn ich tatsächlich "t1.join ()" und "t2.join ()" lösche und ausführe, wird es so.
A1
B1
A2
B2
^CException ignored in: <module 'threading' from '/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py'>
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 1388, in _shutdown
lock.acquire()
KeyboardInterrupt:
Es gab eine Zeit, in der ich dachte: "Wenn es sich um einen Prozess handelt, der While True verwendet, endet er nicht in der Mitte, und wenn Sie mit Strg + C aufhören, ja." Aber es gibt überraschende Szenen, die ich stoppen möchte. Zum Beispiel, wenn Sie den Bot mit einem Befehl herunterfahren möchten. Die folgenden Inhalte wurden zu diesem Zeitpunkt entdeckt.
sys.exit ()
funktioniert auch nichtimport threading
import time
import sys
#Funktionsdefinition
def a():
c=1
while True:
time.sleep(1)
print("A" + str(c))
c+=1
def b():
k=1
time.sleep(0.5)
while True:
time.sleep(1)
print("B" + str(k))
k+=1
#Thread-Objekterstellung
t1 = threading.Thread(target=a)
t2 = threading.Thread(target=b)
#Lauf
t1.start()
t2.start()
#erzwungene Kündigung
print("Terminate")
sys.exit()
print("Terminated")
Die erwartete Ausgabe ist eine "Terminate" -Zeile. Dies liegt daran, dass das Programm nicht nach "sys.exit ()" ausgeführt werden sollte (dies ist streng falsch, wie später beschrieben). Wenn dies jedoch tatsächlich betrieben wird, wird die folgende Ausgabe erhalten.
Terminate
A1
B1
A2
B2
A3
B3
A4
B4
sys.exit ()
wird ausgeführt, nachdem Terminate
und Terminated
ausgeblendet sind, aber die beiden oben genannten Funktionen wurden normal ausgeführt.
Beim Erkennen von "sys.exit ()" ist ein Fehler aufgetreten. Es stoppt nicht das gesamte Programm, es stoppt den Thread.
Der einzige Thread, der im obigen Programm stoppt, ist der Thread, der "print (" Terminate ")" ausführt, und "sys.exit ()" ist nicht bei den beiden Threads angekommen, die sich unendlich wiederholen.
Eine Möglichkeit, dies zu stoppen, besteht darin, sys.exit ()
innerhalb des Thread-Objekts auszuführen.
Aber was ich tun möchte, ist "alle Threads auf einmal stoppen".
Dämonisieren Sie andere Threads als den Haupt-Thread.
import threading
import time
import sys
#Funktionsdefinition
def a():
c=1
while True:
time.sleep(1)
print("A" + str(c))
c+=1
def b():
k=1
time.sleep(0.5)
while True:
time.sleep(1)
print("B" + str(k))
k+=1
def c():
while True:
n = input()
if n == "e":
print("Terminate")
sys.exit()
#Thread-Objekterstellung
t1 = threading.Thread(target=a)
t2 = threading.Thread(target=b)
#Dämonisierung
t1.setDaemon(True)
t2.setDaemon(True)
#Lauf
t1.start()
t2.start()
c() # c()Nur auf dem Haupt-Thread ausführen
Beim Empfang der Eingabe "e" wurde geändert, um "sys.exit ()" auszuführen. Das Ausgabeergebnis ist wie folgt.
A1
B1
A2
e
Terminate
Wenn Sie e und Enter (Return) drücken, wird die Ausführung dort gestoppt. Der Daemon-Thread verhält sich so, dass ** automatisch verschwindet, wenn ein anderer Thread als der Daemon-Thread nicht ausgeführt wird **. Wenn es nur einen Prozess gibt, der "sys.exit ()" enthält, ist es möglicherweise besser, ihn auf dem Hauptthread auszuführen, dh auf der äußersten Seite, ohne "threading.Thread ()" auszuführen.
Um ehrlich zu sein, habe ich versucht, die Ursache herauszufinden, aber ich weiß es nicht. Irgendwie war das Signal so ähnlich, aber ich kann es mit meinen eigenen Fähigkeiten nicht richtig schreiben, also werde ich es nicht posten. Während ich diesen Artikel schrieb, habe ich viel über das Threading recherchiert, aber es scheint, dass es immer noch verschiedene Funktionen gibt und es möglicherweise Möglichkeiten gibt, zu realisieren, was ich tun möchte, außer den oben aufgeführten. Wenn ich jedoch versuche, dies im Rahmen meines Verständnisses zu tun, wird es wie oben sein. Wenn dies stecken bleibt, werde ich versuchen, einen anderen Weg zu finden.