J'ai un module Python qui utilise le multiprocessing
. J'exécute ce module à partir d'un autre script avec runpy
. Cependant, cela se traduit par (1) le module exécutant deux fois , et (2) les travaux de multiprocessing
ne se terminent jamais (le script se bloque juste).
Dans mon travail minimal par exemple, j'ai un script runpy_test.py一:
start done
et un répertoire module_test contenant un __init__ vide .py et un __main__.py
start start
Lorsque j'exécute runpy_test.py , j'obtiens :
from multiprocessing import Pool print 'start' def f(x): return x*x pool = Pool() result = pool.map(f, [1,2,3]) print 'done'
et le script se bloque.
Si je supprime l'appel pool.map
(ou si j'exécute __ main__.py directement, y compris l'appel pool.map
), j'obtiens:
import runpy runpy.run_module('module_test')
J'exécute ceci sur Scientific Linux 7.6 en Python 2.7.5.
3 Réponses :
Essayez de définir votre fonction f
dans un module séparé. Il doit être sérialisé pour être transmis aux processus du pool, puis ces processus doivent le recréer, en important le module dans lequel il se produit. Cependant, le fichier __main__.py
dans lequel il se produit n'est pas un module, ou du moins pas un module bien élevé. Tenter de l'importer entraînerait la création d'un autre pool et un autre appel de la carte, ce qui semble être une recette pour un désastre.
Réécrivez votre __main__.py
comme ceci:
def f(x): return x*x
Et puis écrivez un implementation.py
(vous pouvez appeler cela comme vous want) dans lequel votre fonction est définie:
from multiprocessing import Pool from .implementation import f print 'start' pool = Pool() result = pool.map(f, [1,2,3]) print 'done'
Sinon, vous aurez le même problème avec la plupart des interfaces en multitraitement, et indépendamment de l'utilisation de runpy. Comme @Weeble l'a expliqué, lorsque Pool.map
essaie de charger la fonction f
dans chaque sous-processus, il importera
où votre fonction est définie, mais comme vous avez du code exécutable au niveau du module dans __main__
, il sera réexécuté par le sous-processus.
Hormis cette raison technique, ceci est également une meilleure conception en termes de séparation des préoccupations et des tests. Vous pouvez désormais facilement importer et appeler (y compris à des fins de test) la fonction f
sans l'exécuter en parallèle.
Bien que ce ne soit pas la "bonne" façon de le faire, une solution qui a fonctionné pour moi a été d'utiliser _run_module_as_main
de runpy au lieu de run_module
. C'était idéal pour moi car je travaillais avec le code de quelqu'un d'autre et nécessitais le moins de changements.
Votre
module_test
semble fonctionner correctement sans supprimerpool.map
pour moi.@SreejithMenon Pour clarifier, appelez-vous le module via
runpy
?Non, j'appelle directement le module. Je me demande si l'appeler via runpy est le problème.
@SreejithMenon Désolé, j'aurais dû être plus clair. L'appel direct du module fonctionne aussi pour moi. Ce n'est que lorsque j'essaye via
runpy
que je rencontre ce problème.