GNU/Linux >> Tutoriels Linux >  >> Linux

Impossible de tuer le script Python avec Ctrl-C

Je pense qu'il est préférable d'appeler join() sur vos fils quand vous vous attendez à ce qu'ils meurent. J'ai pris la liberté de modifier vos boucles pour qu'elles se terminent (vous pouvez également y ajouter tous les besoins de nettoyage nécessaires). La variable die est vérifié à chaque passage et lorsqu'il est True , le programme se termine.

import threading
import time

class MyThread (threading.Thread):
    die = False
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.name = name

    def run (self):
        while not self.die:
            time.sleep(1)
            print (self.name)

    def join(self):
        self.die = True
        super().join()

if __name__ == '__main__':
    f = MyThread('first')
    f.start()
    s = MyThread('second')
    s.start()
    try:
        while True:
            time.sleep(2)
    except KeyboardInterrupt:
        f.join()
        s.join()

KeyboardInterrupt et les signaux ne sont vus que par le processus (c'est-à-dire le thread principal) ... Jetez un œil à Ctrl-c c'est-à-dire KeyboardInterrupt pour tuer les threads en python


Ctrl +C termine le thread principal, mais comme vos threads ne sont pas en mode démon, ils continuent de fonctionner, ce qui maintient le processus en vie. Nous pouvons en faire des démons :

f = FirstThread()
f.daemon = True
f.start()
s = SecondThread()
s.daemon = True
s.start()

Mais alors il y a un autre problème - une fois que le thread principal a démarré vos threads, il n'y a rien d'autre à faire. Donc, il sort et les threads sont détruits instantanément. Gardons donc le fil principal en vie :

import time
while True:
    time.sleep(1)

Maintenant, il gardera l'impression 'first' et 'second' jusqu'à ce que vous appuyiez sur Ctrl +C .

Modifier : comme l'ont souligné les commentateurs, les threads démons peuvent ne pas avoir la possibilité de nettoyer des éléments tels que les fichiers temporaires. Si vous en avez besoin, attrapez le KeyboardInterrupt sur le thread principal et faites-le coordonner le nettoyage et l'arrêt. Mais dans de nombreux cas, laisser les threads démons mourir soudainement est probablement suffisant.


Une version améliorée de la réponse de @Thomas K :

  • Définir une fonction d'assistant is_any_thread_alive() selon cet essentiel, qui peut terminer le main() automatiquement.

Exemples de codes :

import threading

def job1():
    ...

def job2():
    ...

def is_any_thread_alive(threads):
    return True in [t.is_alive() for t in threads]

if __name__ == "__main__":
    ...
    t1 = threading.Thread(target=job1,daemon=True)
    t2 = threading.Thread(target=job2,daemon=True)
    t1.start()
    t2.start()

    while is_any_thread_alive([t1,t2]):
        time.sleep(0)

Linux
  1. Changer le répertoire de travail dans le shell avec un script python

  2. nom de base avec des espaces dans un script bash ?

  3. Exécuter le script Python via crontab

  4. ID d'un thread Python tel que rapporté par top

  5. Appelez le script Python à partir de bash avec un argument

Comment écrire un script bash avec des exemples

Comment exécuter une commande Shell avec Python

Comment exécuter un script Python en PHP

Comment installer Python 2.7 sur CentOS 7.1 ou 6.7 avec Anaconda

Déboguer dans pyCharm avec les privilèges sudo ?

Rendre le script Python combiné avec des packages Linux faciles à installer pour l'utilisateur final