web-dev-qa-db-fra.com

Pourquoi l'instance doit-elle être recréée lors du redémarrage d'un thread?

Imaginez les classes suivantes:

Class Object(threading.Thread):
    # some initialisation blabla
    def run(self):
        while True:
            # do something
            sleep(1)

class Checker():
    def check_if_thread_is_alive(self):
        o = Object()
        o.start()

        while True:
            if not o.is_alive():
                o.start()

Je veux redémarrer le fil au cas où il est mort. Cela ne marche pas. Parce que les threads ne peuvent être démarrés qu'une seule fois. Première question. Pourquoi est-ce?

Pour autant que je sache, je dois recréer chaque instance de Object et appeler start() pour redémarrer le thread. En cas de Objects complexe, cela n’est pas très pratique. Je dois lire les valeurs actuelles de l'ancien Object, en créer un nouveau et définir les paramètres dans le nouvel objet avec les anciennes valeurs. Deuxième question: cela peut-il être fait de manière plus intelligente et plus facile?

12
OrangeTux

La raison pour laquelle threading.Thread est implémenté de cette façon est de conserver la correspondance entre un objet thread et le thread du système d'exploitation. Dans les principaux systèmes d’exploitation, les threads ne peuvent pas être redémarrés, mais vous pouvez créer un autre thread avec un autre ID de thread .

Si la recréation pose problème, il n'est pas nécessaire d'hériter de votre classe de threading.Thread, il suffit de passer un paramètre cible au constructeur de Thread, comme suit:

class MyObj(object):
    def __init__(self):
        self.thread = threading.Thread(target=self.run)
    def run(self):
        ...

Ensuite, vous pouvez accéder au membre du thread pour contrôler votre exécution et le recréer au besoin. Aucune récréation MyObj n'est requise.

15
Ellioh

Voir ici: http://docs.python.org/2/library/threading.html#threading.Thread.start

Il doit être appelé au plus une fois par objet de thread. Il fait en sorte que la méthode run () de l’objet soit invoquée dans un thread de contrôle séparé.

Cette méthode lève une RuntimeError si elle est appelée plusieurs fois sur le même objet thread.

Un fil n'est pas destiné à être exécuté plus d'une fois. Vous voudrez peut-être utiliser un Thread Pool

1
Simbi

Je crois que cela a à voir avec la façon dont la classe Thread est implémentée. Il encapsule un vrai thread de système d'exploitation, de sorte que le redémarrage du thread changerait son identité, ce qui pourrait prêter à confusion.

Une meilleure façon de traiter les threads consiste à utiliser des fonctions/appelables cibles:

class Worker(object):
    """ Implements the logic to be run in separate threads """
    def __call__(self):
        #  do useful stuff and change the state

class Supervisor():
    def run(self, worker):
        thr = None
        while True:
            if not thr or not thr.is_alive():
                thr = Thread(target=worker)
                thr.daemon = True
                thr.start()
            thr.join(1)  # give it some time
0
bereal