2 votes

Quelle est la bonne manière de terminer le code multi-threading quand un thread échoue?

J'ai le code suivant :

def getdata3(self, page, data, apifolder, additional):
    tries = 10
    for n in range(tries):
        try:
        except (ChunkedEncodingError, requests.exceptions.HTTPError) as e:
            ...

            if n == tries - 1:
                raise e            # Si arrivé ici - Terminer !
    print ("{2} page {0} finished. Length is {1}".format(page,len(datarALL),str(datetime.now())))
    return job

Code principal :

    with ThreadPoolExecutor(max_workers=num_of_workers) as executor:
        futh = [(executor.submit(self.getdata3, page, data, apifolder,additional)) for page in pages]
        for data in as_completed(futh):
            datarALL.extend(data.result())
    print ("Finished generateing data.")
    return datarALL

Ce code crée des threads pour les travailleurs. Lorsque tout le travail est terminé, il retourne le datarALL.

Mon problème :

Ce que je veux, c'est que si l'un des threads arrive ici :

if n == tries - 1:
    raise e            # Si arrivé ici - Terminer !

Tous les threads existants seront terminés. Aucun nouveau thread ne sera créé (terminer la boucle for page in pages) et le programme entier sera terminé.

J'ai lu quelques articles sur le problème. J'ai également lu cette Devrais-je utiliser des événements, des sémaphores, des verrous, des conditions ou une combinaison de ceux-ci pour gérer la sortie en toute sécurité de mon programme Python multithreadé ? mais les solutions proposées sont très complexes et semblent ajouter beaucoup de code dont je doute avoir besoin.

J'ai essayé de faire :

if n == tries - 1:
    exit(1)      

Mais lorsque je vérifie htop, cela ne ferme pas l'ensemble du processus et des threads... J'en ai quelques-uns qui restent là comme des zombies.

Ma question : Y a-t-il une solution simple et propre pour terminer le programme avec un message d'erreur ?

3voto

Jean-François Fabre Points 94672

sys.exit() peut parfois rester bloqué car il essaie de quitter proprement.

Une solution rapide et sale implique l'utilisation de os._exit(1) (1 est un code de retour possible indiquant une erreur, 0 signifie succès, vous ne voulez pas l'utiliser ici. Restez dans la plage 0-255 pour éviter les problèmes de portabilité)

Sur les systèmes modernes, le suivi des ressources se produit et le programme se ferme, tuant toutes les ressources attachées (manipulateurs de fichiers, threads, mémoire...), il s'agit donc d'une solution acceptable.

L'inconvénient est qu'il contourne les procédures de sortie/nettoyage python, tout comme lorsque vous arrêtez le processus python en utilisant kill. Sur les systèmes d'exploitation qui manquent de gestion du suivi des ressources (nous parlons d'histoire ancienne), cela entraînerait une fuite de mémoire globale/descripteurs de fichiers.

Dans votre cas, cela n'a pas d'importance car sans cela, vous ne pouvez pas quitter votre application. Mais ne le généralisez pas, réservez cela pour les procédures de sortie d'urgence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X