Programme "Je ne peux pas m'arrêter ..." Je "Veuillez arrêter"
Cet article est l'article du 7ème jour du N High School Advent Calendar 2019. Je suis actuellement en deuxième année de ma deuxième année (il y avait beaucoup de choses lors de mon transfert) et je suis en cours scolaire. Je suis très reconnaissant que N High School puisse réaliser son propre projet pendant le temps de programmation tant qu'il termine les tâches essentielles.
Dans cet article, j'écrirai sur les problèmes que j'ai rencontrés lors de la création de bots Discord et Twitter en Python. Veuillez signaler toute erreur.
Lorsque j'ai essayé d'arrêter un programme utilisant le threading Python avec Keyboard Interrupt (Ctrl + C), cela ne s'est pas arrêté immédiatement pour une raison quelconque.
Après une enquête plus approfondie, sys.exit ()
ne s'est pas arrêté.
OS: Windows 10 Home Runtime: Python 3.8.0
Pour le moment, j'ai décidé d'écrire du code en utilisant le threading pour la vérification.
import threading
import time
#Définition des fonctions
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))
#Création d'objets de thread
t1 = threading.Thread(target=a)
t2 = threading.Thread(target=b)
#Courir
t1.start()
t2.start()
#Attends la fin
t1.join()
t2.join()
print("Finish")
Comme prévu, la sortie ressemble à ceci: Fin était affiché en même temps que B4 était affiché.
A0
B0
A1
B1
A2
B2
A3
B3
A4
B4
Finish
Maintenant, remodelons cela en une boucle infinie.
import threading
import time
#Définition des fonctions
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
#Création d'objets de thread
t1 = threading.Thread(target=a)
t2 = threading.Thread(target=b)
#Courir
t1.start()
t2.start()
#Attends la fin
t1.join()
t2.join()
La sortie est la suivante.
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:
Pour une raison quelconque, il ne s'est pas arrêté à la première interruption du clavier. Cette fois, je l'ai fait deux fois et ça s'est arrêté, mais je veux l'éviter si possible.
Vous n'avez pas à "attendre la fin". En d'autres termes, supprimez simplement «**. Join ()».
Quand je supprime t1.join ()
et t2.join ()
et que je l'exécute, cela devient comme ça.
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:
Il fut un temps où je pensais: "Si c'est un processus qui utilise While True, il ne se terminera pas au milieu, et si vous vous arrêtez avec Ctrl + C, oui." Mais il y a des scènes surprenantes que je veux arrêter. Par exemple, lorsque vous souhaitez arrêter le bot avec une commande. Le contenu suivant a été découvert à ce moment-là.
sys.exit ()
ne fonctionne pas non plusimport threading
import time
import sys
#Définition des fonctions
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
#Création d'objets de thread
t1 = threading.Thread(target=a)
t2 = threading.Thread(target=b)
#Courir
t1.start()
t2.start()
#résiliation forcée
print("Terminate")
sys.exit()
print("Terminated")
La sortie attendue est une ligne «Terminer». C'est parce que le programme ne doit pas être exécuté après sys.exit ()
(c'est strictement faux, comme décrit plus loin).
Cependant, lorsque celui-ci est réellement utilisé, la sortie suivante est obtenue.
Terminate
A1
B1
A2
B2
A3
B3
A4
B4
sys.exit ()
s'exécute après que Terminate
et Terminated
soit masqué, mais les deux fonctions ci-dessus ont été exécutées normalement.
Il y a eu une erreur lors de la reconnaissance de sys.exit ()
. Cela n'arrête pas tout le programme, cela arrête le fil.
Le thread qui s'arrête dans le programme ci-dessus est seulement le thread qui exécute print (" Terminate ")
, et sys.exit ()
n'est pas arrivé aux deux threads qui bouclent indéfiniment.
Une façon de l'arrêter est d'exécuter sys.exit ()
dans l'objet thread.
Mais ce que je veux faire, c'est "arrêter tous les threads à la fois".
Faites des threads autres que le thread principal un démon.
import threading
import time
import sys
#Définition des fonctions
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()
#Création d'objets de thread
t1 = threading.Thread(target=a)
t2 = threading.Thread(target=b)
#Diabolisation
t1.setDaemon(True)
t2.setDaemon(True)
#Courir
t1.start()
t2.start()
c() # c()Exécuter uniquement sur le thread principal
Changé pour exécuter sys.exit ()
lors de la réception de l'entrée ʻe`.
Le résultat de sortie est le suivant.
A1
B1
A2
e
Terminate
Si vous appuyez sur e et appuyez sur Entrée (Retour), l'exécution s'arrêtera là.
Le thread démon se comporte comme ** disparaît automatiquement lorsqu'un thread autre que le thread démon n'est pas en cours d'exécution **.
S'il n'y a qu'un seul processus qui inclut sys.exit ()
, il peut être préférable de l'exécuter sur le thread principal, c'est-à-dire sur le côté le plus extérieur sans faire threading.Thread ()
.
Pour être honnête, j'ai essayé de découvrir la cause, mais je ne sais pas. D'une manière ou d'une autre, le signal était quelque chose comme ça, mais je ne peux pas l'écrire correctement avec mes propres compétences, donc je ne le posterai pas. Au cours de la rédaction de cet article, j'ai beaucoup recherché sur le threading, mais il semble qu'il existe encore diverses fonctions, et il peut y avoir des moyens de réaliser ce que je veux faire en dehors de celles énumérées ci-dessus. Cependant, si j'essaye de le faire dans le cadre de ma compréhension, ce sera comme ci-dessus. Si cela reste bloqué, je vais essayer de trouver un autre moyen.