En général, tuer brusquement des threads est considéré comme une mauvaise pratique de programmation. Tuer brusquement un thread peut laisser ouverte une ressource critique qui doit être fermée correctement. Mais vous souhaiterez peut-être tuer un thread une fois qu'une période de temps spécifique s'est écoulée ou qu'une interruption a été générée. Il existe différentes méthodes par lesquelles vous pouvez tuer un thread en python.
- Lever des exceptions dans un thread python
- Définir/réinitialiser le drapeau d'arrêt
- Utiliser des traces pour tuer les threads
- Utiliser le module multitraitement pour tuer les threads
- Tuer le thread Python en le définissant comme démon
- Utiliser une fonction cachée _stop()
Lever des exceptions dans un thread python :
Cette méthode utilise la fonction PyThreadState_SetAsyncExc() pour déclencher une exception dans un thread. Par exemple,
Python3
Madhuri a dit allez
# Python program raising> # exceptions in a python> # thread> import> threading> import> ctypes> import> time> > class> thread_with_exception(threading.Thread):> >def> __init__(>self>, name):> >threading.Thread.__init__(>self>)> >self>.name>=> name> > >def> run(>self>):> ># target function of the thread class> >try>:> >while> True>:> >print>(>'running '> +> self>.name)> >finally>:> >print>(>'ended'>)> > >def> get_id(>self>):> ># returns id of the respective thread> >if> hasattr>(>self>,>'_thread_id'>):> >return> self>._thread_id> >for> id>, thread>in> threading._active.items():> >if> thread>is> self>:> >return> id> > >def> raise_exception(>self>):> >thread_id>=> self>.get_id()> >res>=> ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,> >ctypes.py_object(SystemExit))> >if> res>>1>:> >ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,>0>)> >print>(>'Exception raise failure'>)> > t1>=> thread_with_exception(>'Thread 1'>)> t1.start()> time.sleep(>2>)> t1.raise_exception()> t1.join()> |
>
>
Lorsque nous exécutons le code ci-dessus sur une machine et que vous remarquerez que dès que la fonction raise_exception() est appelée, la fonction cible run() se termine. En effet, dès qu'une exception est levée, le contrôle du programme sort du bloc try et la fonction run() prend fin. Après cela, la fonction join() peut être appelée pour tuer le thread. En l'absence de la fonction run_exception(), la fonction cible run() continue de s'exécuter indéfiniment et la fonction join() n'est jamais appelée pour tuer le thread.
Définir/Réinitialiser le drapeau d'arrêt :
Afin de tuer un thread, nous pouvons déclarer un indicateur d'arrêt et cet indicateur sera vérifié occasionnellement par le thread. Par exemple
Python3
# Python program showing> # how to kill threads> # using set/reset stop> # flag> import> threading> import> time> def> run():> >while> True>:> >print>(>'thread running'>)> >global> stop_threads> >if> stop_threads:> >break> stop_threads>=> False> t1>=> threading.Thread(target>=> run)> t1.start()> time.sleep(>1>)> stop_threads>=> True> t1.join()> print>(>'thread killed'>)> |
>
>
Dans le code ci-dessus, dès que la variable globale stop_threads est définie, la fonction cible run() se termine et le thread t1 peut être tué en utilisant t1.join(). Mais on peut s'abstenir d'utiliser une variable globale pour certaines raisons. Dans ces situations, des objets fonction peuvent être transmis pour fournir une fonctionnalité similaire à celle indiquée ci-dessous.
Python3
# Python program killing> # threads using stop> # flag> import> threading> import> time> def> run(stop):> >while> True>:> >print>(>'thread running'>)> >if> stop():> >break> > def> main():> >stop_threads>=> False> >t1>=> threading.Thread(target>=> run, args>=>(>lambda> : stop_threads, ))> >t1.start()> >time.sleep(>1>)> >stop_threads>=> True> >t1.join()> >print>(>'thread killed'>)> main()> |
>
fonction chr python
>
L'objet fonction passé dans le code ci-dessus renvoie toujours la valeur de la variable locale stop_threads. Cette valeur est vérifiée dans la fonction run(), et dès que stop_threads est réinitialisé, la fonction run() se termine et le thread peut être tué.
Utiliser des traces pour tuer les threads :
Cette méthode fonctionne en installant traces dans chaque fil. Chaque trace se termine lors de la détection d'un stimulus ou d'un indicateur, tuant ainsi instantanément le thread associé. Par exemple
Python3
# Python program using> # traces to kill threads> import> sys> import> trace> import> threading> import> time> class> thread_with_trace(threading.Thread):> >def> __init__(>self>,>*>args,>*>*>keywords):> >threading.Thread.__init__(>self>,>*>args,>*>*>keywords)> >self>.killed>=> False> >def> start(>self>):> >self>.__run_backup>=> self>.run> >self>.run>=> self>.__run> >threading.Thread.start(>self>)> >def> __run(>self>):> >sys.settrace(>self>.globaltrace)> >self>.__run_backup()> >self>.run>=> self>.__run_backup> >def> globaltrace(>self>, frame, event, arg):> >if> event>=>=> 'call'>:> >return> self>.localtrace> >else>:> >return> None> >def> localtrace(>self>, frame, event, arg):> >if> self>.killed:> >if> event>=>=> 'line'>:> >raise> SystemExit()> >return> self>.localtrace> >def> kill(>self>):> >self>.killed>=> True> def> func():> >while> True>:> >print>(>'thread running'>)> t1>=> thread_with_trace(target>=> func)> t1.start()> time.sleep(>2>)> t1.kill()> t1.join()> if> not> t1.isAlive():> >print>(>'thread killed'>)> |
>
>
Dans ce code, start() est légèrement modifié pour définir la fonction de trace système en utilisant settrace() . La fonction de trace locale est définie de telle sorte que, chaque fois que l'indicateur kill (killed) du thread respectif est défini, une exception SystemExit est déclenchée lors de l'exécution de la ligne de code suivante, ce qui met fin à l'exécution de la fonction cible func. Le thread peut maintenant être tué avec join().
Utilisation du module multitraitement pour tuer les threads :
Le module multitraitement de Python vous permet de générer des processus de la même manière que vous générez des threads à l'aide du module de threading. L'interface du module multithreading est similaire à celle du module threading. Par exemple, dans un code donné nous avons créé trois threads (processus) qui comptent de 1 à 9.
Python3
# Python program creating> # three threads> import> threading> import> time> # counts from 1 to 9> def> func(number):> >for> i>in> range>(>1>,>10>):> >time.sleep(>0.01>)> >print>(>'Thread '> +> str>(number)>+> ': prints '> +> str>(number>*>i))> # creates 3 threads> for> i>in> range>(>0>,>3>):> >thread>=> threading.Thread(target>=>func, args>=>(i,))> >thread.start()> |
>
>
La fonctionnalité du code ci-dessus peut également être implémentée en utilisant le module multitraitement de la même manière, avec très peu de modifications. Voir le code donné ci-dessous.
Python3
# Python program creating> # thread using multiprocessing> # module> import> multiprocessing> import> time> def> func(number):> >for> i>in> range>(>1>,>10>):> >time.sleep(>0.01>)> >print>(>'Processing '> +> str>(number)>+> ': prints '> +> str>(number>*>i))> for> i>in> range>(>0>,>3>):> >process>=> multiprocessing.Process(target>=>func, args>=>(i,))> >process.start()> |
jeux d'images pour Android
>
>
Bien que l'interface des deux modules soit similaire, les deux modules ont des implémentations très différentes. Tous les threads partagent des variables globales, alors que les processus sont complètement séparés les uns des autres. Par conséquent, la suppression de processus est beaucoup plus sûre que la suppression de threads. La classe Process est fournie une méthode, mettre fin() , pour tuer un processus. Maintenant, revenons au problème initial. Supposons que dans le code ci-dessus, nous voulions tuer tous les processus après 0,03 s. Cette fonctionnalité est obtenue à l'aide du module multitraitement dans le code suivant.
dérivé partiel du latex
Python3
# Python program killing> # a thread using multiprocessing> # module> import> multiprocessing> import> time> def> func(number):> >for> i>in> range>(>1>,>10>):> >time.sleep(>0.01>)> >print>(>'Processing '> +> str>(number)>+> ': prints '> +> str>(number>*>i))> # list of all processes, so that they can be killed afterwards> all_processes>=> []> for> i>in> range>(>0>,>3>):> >process>=> multiprocessing.Process(target>=>func, args>=>(i,))> >process.start()> >all_processes.append(process)> # kill all processes after 0.03s> time.sleep(>0.03>)> for> process>in> all_processes:> >process.terminate()> |
>
>
Bien que les deux modules aient des implémentations différentes. Cette fonctionnalité fournie par le module multitraitement dans le code ci-dessus est similaire à la suppression de threads. Par conséquent, le module multitraitement peut être utilisé comme un simple alternative chaque fois que nous devons implémenter la suppression des threads en Python.
Tuer le thread Python en le définissant comme démon :
Threads démons sont ces threads qui sont tués lorsque le programme principal se termine. Par exemple
Python3
import> threading> import> time> import> sys> def> func():> >while> True>:> >time.sleep(>0.5>)> >print>(>'Thread alive, and it won't die on program termination'>)> t1>=> threading.Thread(target>=>func)> t1.start()> time.sleep(>2>)> sys.exit()> |
>
>
Notez que le thread t1 reste actif et empêche le programme principal de se terminer via sys.exit(). En Python, tout thread non-démon actif bloque la sortie du programme principal. Alors que les threads démons eux-mêmes sont tués dès la fermeture du programme principal. En d’autres termes, dès que le programme principal se termine, tous les threads démons sont tués. Pour déclarer un thread comme démon, nous définissons l'argument mot-clé démon sur True. Par exemple, dans le code donné, il démontre la propriété des threads démons.
Python3
# Python program killing> # thread using daemon> import> threading> import> time> import> sys> def> func():> >while> True>:> >time.sleep(>0.5>)> >print>(>'Thread alive, but it will die on program termination'>)> t1>=> threading.Thread(target>=>func)> t1.daemon>=> True> t1.start()> time.sleep(>2>)> sys.exit()> |
>
>
Notez que dès que le programme principal se termine, le thread t1 est tué. Cette méthode s'avère extrêmement utile dans les cas où la fin du programme peut être utilisée pour déclencher la suppression des threads. Notez qu'en Python, le programme principal se termine dès que tous les threads non démons sont morts, quel que soit le nombre de threads démons actifs. Par conséquent, les ressources détenues par ces threads démons, telles que les fichiers ouverts, les transactions de base de données, etc., peuvent ne pas être libérées correctement. Le thread de contrôle initial dans un programme python n'est pas un thread démon. Il n'est pas recommandé de tuer un thread de force, sauf si l'on sait avec certitude que cela ne provoquera pas de fuites ou de blocages.
Utiliser une fonction cachée _stop() :
Afin de tuer un thread, nous utilisons la fonction cachée _stop(). Cette fonction n'est pas documentée mais pourrait disparaître dans la prochaine version de python.
Python3
# Python program killing> # a thread using ._stop()> # function> import> time> import> threading> class> MyThread(threading.Thread):> ># Thread class with a _stop() method.> ># The thread itself has to check> ># regularly for the stopped() condition.> >def> __init__(>self>,>*>args,>*>*>kwargs):> >super>(MyThread,>self>).__init__(>*>args,>*>*>kwargs)> >self>._stop>=> threading.Event()> ># function using _stop function> >def> stop(>self>):> >self>._stop.>set>()> >def> stopped(>self>):> >return> self>._stop.isSet()> >def> run(>self>):> >while> True>:> >if> self>.stopped():> >return> >print>(>'Hello, world!'>)> >time.sleep(>1>)> t1>=> MyThread()> t1.start()> time.sleep(>5>)> t1.stop()> t1.join()> |
>
pointeurs en c
>
Note: Les méthodes ci-dessus peuvent ne pas fonctionner dans une situation ou une autre, car Python ne fournit aucune méthode directe pour tuer les threads.