Dans le module multitraitement de Python, la classe Pool offre un moyen pratique de répartir les tâches sur plusieurs processus. Cependant, la gestion des événements KeyboardInterrupt dans les pools peut être difficile, comme le démontre l'extrait de code :
<code class="python">from multiprocessing import Pool from time import sleep from sys import exit def slowly_square(i): sleep(1) return i*i def go(): pool = Pool(8) try: results = pool.map(slowly_square, range(40)) except KeyboardInterrupt: # **** THIS PART NEVER EXECUTES. **** pool.terminate() print "You cancelled the program!" sys.exit(1) print "\nFinally, here are the results: ", results if __name__ == "__main__": go()</code>
Lors de l'exécution de ce code, appuyer sur Ctrl C ne déclenchera pas le processus de nettoyage, laissant les sous-processus s'exécuter indéfiniment. Pour résoudre ce problème, envisagez la solution de contournement suivante :
Le comportement observé dans le code est une conséquence d'un bug Python. KeyboardInterrupt n'est pas envoyé lors de l'attente d'une condition dans threading.Condition.wait(). Comme Pool.map() utilise une condition d'attente en interne, l'interruption n'est jamais reçue.
Une solution consiste à utiliser Pool.map_async(), qui permet de spécifier un timeout. En définissant un délai d'attente suffisamment long (par exemple, 9999999), nous pouvons garantir que l'interruption sera déclenchée dans un délai raisonnable.
Par conséquent, remplacez :
<code class="python"> results = pool.map(slowly_square, range(40))</code>
par :
<code class="python"> results = pool.map_async(slowly_square, range(40)).get(9999999)</code>
Cette solution de contournement fournit un moyen de gérer correctement les événements KeyboardInterrupt dans les pools multitraitements, permettant ainsi l'arrêt de tous les sous-processus lorsque l'utilisateur annule le programme.
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!