Cet article vous apporte une introduction détaillée au positionnement et à la destruction dans les threads Python (avec des exemples). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Je sentais que quelque chose n'allait pas avant le début du travail et j'avais l'impression que j'allais en assumer la responsabilité. Non, c’est le troisième jour de travail qui me fait culpabiliser.
Nous avons un programme d'arrière-plan incroyable qui peut charger dynamiquement des modules et les exécuter de manière threadée. De cette manière, les fonctions du plug-in sont réalisées. Lorsque le module est mis à jour, le programme en arrière-plan lui-même ne se fermera pas. Il fermera uniquement le thread correspondant au module, mettra à jour le code puis le démarrera.
J'ai donc écrit un module pour montrer mes compétences, mais j'ai oublié d'écrire la fonction de sortie, ce qui entraînait la création d'un nouveau thread à chaque fois que le module était mis à jour. À moins que le programme ne soit redémarré, ces threads seraient créés. rester en vie.
Ce n'est pas possible. Il faut trouver un moyen de le nettoyer, sinon j'ai peur qu'il explose.
Alors comment le nettoyer ? Tout ce à quoi je pense, c'est deux étapes :
Découvrez le numéro de fil qui doit être nettoyé
Détruisez-les ; 🎜>
#coding: utf8 import threading import os import time def tt(): info = threading.currentThread() while True: print 'pid: ', os.getpid() print info.name, info.ident time.sleep(3) t1 = threading.Thread(target=tt) t1.setName('OOOOOPPPPP') t1.setDaemon(True) t1.start() t2 = threading.Thread(target=tt) t2.setName('EEEEEEEEE') t2.setDaemon(True) t2.start() t1.join() t2.join()
root@10-46-33-56:~# python t.py pid: 5613 OOOOOPPPPP 139693508122368 pid: 5613 EEEEEEEEE 139693497632512 ...
root@10-46-33-56:~# ps -Tp 5613 PID SPID TTY TIME CMD 5613 5613 pts/2 00:00:00 python 5613 5614 pts/2 00:00:00 python 5613 5615 pts/2 00:00:00 python
#include<stdio.h> #include<sys> #include<sys> #include<pthread.h> void *test(void *name) { pid_t pid, tid; pid = getpid(); tid = syscall(__NR_gettid); char *tname = (char *)name; // 设置线程名字 prctl(PR_SET_NAME, tname); while(1) { printf("pid: %d, thread_id: %u, t_name: %s\n", pid, tid, tname); sleep(3); } } int main() { pthread_t t1, t2; void *ret; pthread_create(&t1, NULL, test, (void *)"Love_test_1"); pthread_create(&t2, NULL, test, (void *)"Love_test_2"); pthread_join(t1, &ret); pthread_join(t2, &ret); }</pthread.h></sys></sys></stdio.h>
root@10-46-33-56:~# gcc t.c -lpthread && ./a.out pid: 5575, thread_id: 5577, t_name: Love_test_2 pid: 5575, thread_id: 5576, t_name: Love_test_1 pid: 5575, thread_id: 5577, t_name: Love_test_2 pid: 5575, thread_id: 5576, t_name: Love_test_1 ...
root@10-46-33-56:~# ps -Tp 5575 PID SPID TTY TIME CMD 5575 5575 pts/2 00:00:00 a.out 5575 5576 pts/2 00:00:00 Love_test_1 5575 5577 pts/2 00:00:00 Love_test_2
, jetons un coup d'œil à la définition : setName
[threading.py] class Thread(_Verbose): ... @property def name(self): """A string used for identification purposes only. It has no semantics. Multiple threads may be given the same name. The initial name is set by the constructor. """ assert self.__initialized, "Thread.__init__() not called" return self.__name @name.setter def name(self, name): assert self.__initialized, "Thread.__init__() not called" self.__name = str(name) def setName(self, name): self.name = name ...
, et il n'a pas touché les fondamentaux. Ensuite, je ne peux absolument pas le voir ~Thread
ou ps
, nous ne pouvons donc le résoudre qu'à l'intérieur. Python. /proc/
peut parfaitement résoudre ce problème ! Pourquoi ?threading.enumerate
objets thread actifs, à l'exclusion de ceux terminés et non démarrés.
[threading.py] def enumerate(): """Return a list of all Thread objects currently alive. The list includes daemonic threads, dummy thread objects created by current_thread(), and the main thread. It excludes terminated threads and threads that have not yet been started. """ with _active_limbo_lock: return _active.values() + _limbo.values()
#coding: utf8 import threading import os import time def get_thread(): pid = os.getpid() while True: ts = threading.enumerate() print '------- Running threads On Pid: %d -------' % pid for t in ts: print t.name, t.ident print time.sleep(1) def tt(): info = threading.currentThread() pid = os.getpid() while True: print 'pid: {}, tid: {}, tname: {}'.format(pid, info.name, info.ident) time.sleep(3) return t1 = threading.Thread(target=tt) t1.setName('Thread-test1') t1.setDaemon(True) t1.start() t2 = threading.Thread(target=tt) t2.setName('Thread-test2') t2.setDaemon(True) t2.start() t3 = threading.Thread(target=get_thread) t3.setName('Checker') t3.setDaemon(True) t3.start() t1.join() t2.join() t3.join()
root@10-46-33-56:~# python t_show.py pid: 6258, tid: Thread-test1, tname: 139907597162240 pid: 6258, tid: Thread-test2, tname: 139907586672384 ------- Running threads On Pid: 6258 ------- MainThread 139907616806656 Thread-test1 139907597162240 Checker 139907576182528 Thread-test2 139907586672384 ------- Running threads On Pid: 6258 ------- MainThread 139907616806656 Thread-test1 139907597162240 Checker 139907576182528 Thread-test2 139907586672384 ------- Running threads On Pid: 6258 ------- MainThread 139907616806656 Thread-test1 139907597162240 Checker 139907576182528 Thread-test2 139907586672384 ------- Running threads On Pid: 6258 ------- MainThread 139907616806656 Checker 139907576182528 ...
et Thread-test1
Ils affichent tous le pid actuel, l'identifiant du thread et le nom du thread, puis quittent après 3 secondes. Il s'agit de simuler la sortie normale du thread. Thread-test2
génère tous les threads actifs du processus en cours jusqu'à Checker
chaque seconde. threading.enumerate
et Thread-test1
sont visibles au début. Lorsqu'ils sortent, il ne reste que Thread-test2
et MainThread
eux-mêmes. Checker
soit devenu noir et fou, et que nous devions l'arrêter, alors nous pouvons le résoudre de cette façon : Thread-test2
def _async_raise(tid, exctype): """raises the exception, performs cleanup if needed""" tid = ctypes.c_long(tid) if not inspect.isclass(exctype): exctype = type(exctype) res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) if res == 0: raise ValueError("invalid thread id") elif res != 1: ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) raise SystemError("PyThreadState_SetAsyncExc failed") def stop_thread(thread): _async_raise(thread.ident, SystemExit) def get_thread(): pid = os.getpid() while True: ts = threading.enumerate() print '------- Running threads On Pid: %d -------' % pid for t in ts: print t.name, t.ident, t.is_alive() if t.name == 'Thread-test2': print 'I am go dying! Please take care of yourself and drink more hot water!' stop_thread(t) print time.sleep(1)
root@10-46-33-56:~# python t_show.py pid: 6362, tid: 139901682108160, tname: Thread-test1 pid: 6362, tid: 139901671618304, tname: Thread-test2 ------- Running threads On Pid: 6362 ------- MainThread 139901706389248 True Thread-test1 139901682108160 True Checker 139901661128448 True Thread-test2 139901671618304 True Thread-test2: I am go dying. Please take care of yourself and drink more hot water! ------- Running threads On Pid: 6362 ------- MainThread 139901706389248 True Thread-test1 139901682108160 True Checker 139901661128448 True Thread-test2 139901671618304 True Thread-test2: I am go dying. Please take care of yourself and drink more hot water! pid: 6362, tid: 139901682108160, tname: Thread-test1 ------- Running threads On Pid: 6362 ------- MainThread 139901706389248 True Thread-test1 139901682108160 True Checker 139901661128448 True // Thread-test2 已经不在了
comme ça, il se soucie toujours de nous : Thread-test2
Boire plus d'eau chaude ,
;
N'utilisez pas cette méthode en dernier recours, car il existe une certaine probabilité de déclencher des problèmes indescriptibles. Souviens-toi! Ne me demandez pas pourquoi je sais...Pourquoi est-il si difficile d'arrêter un thread ?Le multithread lui-même est conçu pour la concurrence collaborative dans le cadre du processus. unité de planification. Les threads partagent les ressources, il y aura donc de nombreux mécanismes de verrouillage et contrôles d’état. Si vous utilisez la force pour tuer des threads, il y a de fortes chances que des bugs inattendus se produisent. Et la libération la plus importante des ressources de verrouillage peut également provoquer des problèmes inattendus.Nous ne pouvons même pas tuer les threads directement comme tuer des processus via des signaux, car kill ne peut répondre à nos attentes qu'en traitant des processus, mais il n'est évidemment pas possible de traiter les threads, quel que soit le thread qui est tué, l'ensemble du processus. va sortir!
Et à cause du GIL, de nombreux enfants pensent que les threads de Python sont implémentés par Python lui-même et n'existent pas réellement. Python devrait pouvoir les détruire directement, n'est-ce pas ?
Cependant, en fait, les threads de Python sont de vrais threads !
Qu'est-ce que cela signifie ? Les threads Python sont des threads natifs créés par le système d'exploitation via pthread. Python utilise uniquement GIL pour contraindre ces threads afin de décider quand commencer la planification. Par exemple, après avoir exécuté un certain nombre d'instructions, le GIL sera remis. Quant à savoir qui remportera l'oiran, cela dépend du système d'exploitation.
S'il s'agit d'un simple fil de discussion, le système dispose en fait d'un moyen d'y mettre fin, tel que : pthread_exit
, pthread_kill
ou pthread_cancel
Pour plus de détails, veuillez consulter : https://www. cnblogs.com/Creat ..
Quel dommage : Il n'y a pas d'encapsulation de ces méthodes au niveau Python ! Oh mon Dieu, tellement en colère ! Peut-être que les gens pensent que les fils doivent être traités avec douceur.
Si vous voulez quitter un fil de discussion en douceur, c'est presque un non-sens~
Soit quitter après l'exécution, soit définir le bit d'indicateur, et vérifiez fréquemment le bit d'indicateur. Si vous devez quitter, quittez simplement.
"Comment terminer correctement un thread enfant en cours d'exécution" : https://www.cnblogs.com/Creat...
"Ne détruisez pas grossièrement les threads python" :http://xiaorui.cc/2017/02/22/...
Bienvenue à tous les experts pour donner des conseils et échanger, groupe de discussion QQ : 258498217
Veuillez noter la réimpression de la source Ming : https://segmentfault.com/a/11...
c
linux266 lectures Il faut 30 minutes pour lire
ContexteAvant de commencer le travail, je sentais que quelque chose n'allait pas et j'avais l'impression que j'allais en prendre la responsabilité. Non, c’est le troisième jour de travail qui me fait culpabiliser. Nous avons un programme d'arrière-plan incroyable qui peut charger dynamiquement des modules et les exécuter dans des threads. De cette manière, les fonctions du plug-in peuvent être réalisées. Lorsque le module est mis à jour, le programme en arrière-plan lui-même ne se fermera pas. Il fermera uniquement le thread correspondant au module, mettra à jour le code puis le démarrera. J'ai donc écrit un module pour montrer mes compétences, mais j'ai oublié d'écrire la fonction de sortie, ce qui a entraîné la création d'un nouveau thread à chaque fois que le module était mis à jour. À moins que le programme ne soit redémarré, ces threads seraient créés. rester en vie. Ce n'est pas possible. Il faut trouver un moyen de le nettoyer, sinon j'ai peur qu'il explose. Alors comment le nettoyer ? Tout ce à quoi je pense, c'est deux étapes :
Détruisez-les ; 🎜>
Découvrez l'ID du filSemblable au dépannage habituel, vérifiez d'abord l'état du fil du processus cible via la commande ps, car le nom du fil a été défini par setName, donc normalement je devrais voir le fil de discussion correspondant. Utilisez directement le code suivant pour simuler ce fil : Version Python du multi-threadingNormalement, ça ne devrait pas être comme ça, je suis un peu confus. Est-ce que je me souviens mal de tout. le long de? Utilisez une autre version linguistique du multi-threading pour tester :
Vérifiez à nouveau avec la commande PS :
#coding: utf8 import threading import os import time def tt(): info = threading.currentThread() while True: print 'pid: ', os.getpid() print info.name, info.ident time.sleep(3) t1 = threading.Thread(target=tt) t1.setName('OOOOOPPPPP') t1.setDaemon(True) t1.start() t2 = threading.Thread(target=tt) t2.setName('EEEEEEEEE') t2.setDaemon(True) t2.start() t1.join() t2.join()
C'est exact, le nom du fil est effectivement visible via PS !
root@10-46-33-56:~# python t.py pid: 5613 OOOOOPPPPP 139693508122368 pid: 5613 EEEEEEEEE 139693497632512 ...
, jetons un coup d'œil à la définition :
root@10-46-33-56:~# ps -Tp 5613 PID SPID TTY TIME CMD 5613 5613 pts/2 00:00:00 python 5613 5614 pts/2 00:00:00 python 5613 5615 pts/2 00:00:00 python
Ce que vous voyez ici définit simplement les propriétés de l'objet
, et il n'a pas touché les fondamentaux. Ensuite, je ne peux absolument pas le voir ~Il semble que nous ne puissions plus rechercher les noms de threads python en externe par des moyens tels que#include<stdio.h> #include<sys> #include<sys> #include<pthread.h> void *test(void *name) { pid_t pid, tid; pid = getpid(); tid = syscall(__NR_gettid); char *tname = (char *)name; // 设置线程名字 prctl(PR_SET_NAME, tname); while(1) { printf("pid: %d, thread_id: %u, t_name: %s\n", pid, tid, tname); sleep(3); } } int main() { pthread_t t1, t2; void *ret; pthread_create(&t1, NULL, test, (void *)"Love_test_1"); pthread_create(&t2, NULL, test, (void *)"Love_test_2"); pthread_join(t1, &ret); pthread_join(t2, &ret); }</pthread.h></sys></sys></stdio.h>
, nous ne pouvons donc le résoudre qu'à l'intérieur. Python.
root@10-46-33-56:~# gcc t.c -lpthread && ./a.out pid: 5575, thread_id: 5577, t_name: Love_test_2 pid: 5575, thread_id: 5576, t_name: Love_test_1 pid: 5575, thread_id: 5577, t_name: Love_test_2 pid: 5575, thread_id: 5576, t_name: Love_test_1 ...
root@10-46-33-56:~# ps -Tp 5575 PID SPID TTY TIME CMD 5575 5575 pts/2 00:00:00 a.out 5575 5576 pts/2 00:00:00 Love_test_1 5575 5577 pts/2 00:00:00 Love_test_2
objets threadsetName
actifs, à l'exclusion de ceux terminés et non démarrés.
[threading.py] class Thread(_Verbose): ... @property def name(self): """A string used for identification purposes only. It has no semantics. Multiple threads may be given the same name. The initial name is set by the constructor. """ assert self.__initialized, "Thread.__init__() not called" return self.__name @name.setter def name(self, name): assert self.__initialized, "Thread.__init__() not called" self.__name = str(name) def setName(self, name): self.name = name ...
Parce que nous obtenons l'objet Thread, nous pouvons obtenir les informations liées au fil de discussion grâce à cela ! Thread
ps
/proc/
Sortie :
et threading.enumerate
Ils affichent tous le pid actuel, l'identifiant du thread et le nom du thread, puis quittent après 3 secondes. Il s'agit de simuler la sortie normale du thread.
Et le thread génère tous les threads actifs du processus en cours jusqu'à chaque seconde.
[threading.py] def enumerate(): """Return a list of all Thread objects currently alive. The list includes daemonic threads, dummy thread objects created by current_thread(), and the main thread. It excludes terminated threads and threads that have not yet been started. """ with _active_limbo_lock: return _active.values() + _limbo.values()
et
sont visibles au début. Lorsqu'ils sortent, il ne reste queet
eux-mêmes.#coding: utf8 import threading import os import time def get_thread(): pid = os.getpid() while True: ts = threading.enumerate() print '------- Running threads On Pid: %d -------' % pid for t in ts: print t.name, t.ident print time.sleep(1) def tt(): info = threading.currentThread() pid = os.getpid() while True: print 'pid: {}, tid: {}, tname: {}'.format(pid, info.name, info.ident) time.sleep(3) return t1 = threading.Thread(target=tt) t1.setName('Thread-test1') t1.setDaemon(True) t1.start() t2 = threading.Thread(target=tt) t2.setName('Thread-test2') t2.setDaemon(True) t2.start() t3 = threading.Thread(target=get_thread) t3.setName('Checker') t3.setDaemon(True) t3.start() t1.join() t2.join() t3.join()
Détruisez le fil spécifié
root@10-46-33-56:~# python t_show.py pid: 6258, tid: Thread-test1, tname: 139907597162240 pid: 6258, tid: Thread-test2, tname: 139907586672384 ------- Running threads On Pid: 6258 ------- MainThread 139907616806656 Thread-test1 139907597162240 Checker 139907576182528 Thread-test2 139907586672384 ------- Running threads On Pid: 6258 ------- MainThread 139907616806656 Thread-test1 139907597162240 Checker 139907576182528 Thread-test2 139907586672384 ------- Running threads On Pid: 6258 ------- MainThread 139907616806656 Thread-test1 139907597162240 Checker 139907576182528 Thread-test2 139907586672384 ------- Running threads On Pid: 6258 ------- MainThread 139907616806656 Checker 139907576182528 ...
Thread-test1
Supposons maintenant que Thread-test2
soit devenu noir et fou, et que nous devions l'arrêter, alors nous pouvons le résoudre de cette façon :
Sur la base du code ci-dessus, ajoutez et complétez Le code suivant : Checker
threading.enumerate
Thread-test1
Thread-test2
Après une opération, même si nous traitons MainThread
comme ça, il se soucie toujours de nous : Checker
Boire plus d'eau chaude
Retour à l'histoire principale, la méthode ci-dessus est extrêmement grossière. Pourquoi dites-vous cela ?
Parce que son principe est le suivant : utiliser l'API intégrée de Python pour déclencher une exception sur le thread spécifié, lui permettant de se fermer automatiquement
;
N'utilisez pas cette méthode en dernier recours, car il existe une certaine probabilité de déclencher des problèmes indescriptibles. Souviens-toi! Ne me demandez pas pourquoi je sais...
Le multithread lui-même est conçu pour la concurrence collaborative dans le cadre du processus. unité de planification. Les threads partagent les ressources, il y aura donc de nombreux mécanismes de verrouillage et contrôles d’état.
Si vous utilisez la force pour tuer des threads, il y a de fortes chances que des bugs inattendus se produisent. Et la libération la plus importante des ressources de verrouillage peut également provoquer des problèmes inattendus.
Nous ne pouvons même pas tuer le thread directement comme tuer le processus via un signal, car kill ne peut répondre à nos attentes qu'en traitant des processus, mais il n'est évidemment pas possible de traiter les threads, quel que soit le thread. est tué, tout le processus se terminera !
Et à cause du GIL, de nombreux enfants pensent que les threads de Python sont implémentés par Python lui-même et n'existent pas réellement. Python devrait pouvoir les détruire directement, n'est-ce pas ?
Cependant, en fait, les threads de Python sont de vrais threads !
Qu'est-ce que cela signifie ? Les threads Python sont des threads natifs créés par le système d'exploitation via pthread. Python utilise uniquement GIL pour contraindre ces threads afin de décider quand commencer la planification. Par exemple, après avoir exécuté un certain nombre d'instructions, le GIL sera remis. Quant à savoir qui remportera l'oiran, cela dépend du système d'exploitation.
S'il s'agit d'un simple fil de discussion, le système dispose en fait d'un moyen d'y mettre fin, tel que : pthread_exit
, pthread_kill
ou pthread_cancel
Pour plus de détails, veuillez consulter : https://www. cnblogs.com/Creat ..
Quel dommage : Il n'y a pas d'encapsulation de ces méthodes au niveau Python ! Oh mon Dieu, tellement en colère ! Peut-être que les gens pensent que les fils doivent être traités avec douceur.
Si vous voulez quitter un fil de discussion en douceur, c'est presque un non-sens~
Soit quitter après l'exécution, soit définir le bit d'indicateur, et vérifiez fréquemment le bit d'indicateur. Si vous devez quitter, quittez simplement.
"Comment terminer correctement un thread enfant en cours d'exécution" : https://www.cnblogs.com/Creat...
"Ne détruisez pas grossièrement les threads python" :http://xiaorui.cc/2017/02/22/...
Bienvenue à tous les experts pour donner des conseils et échanger, groupe de discussion QQ : 258498217
Veuillez noter la réimpression de la source Ming : https://segmentfault.com/a/11...
Tous droits réservés
Si vous pensez que mon article vous est utile, n'hésitez pas à le féliciter
2 commentaires Tri temporel
Si c'était moi qui pouvais tuer -9, je préférerais en tuer mille par erreur plutôt que d'en laisser un partir, palourde
Répondre
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!