web-dev-qa-db-fra.com

subprocess.wait () n'attend pas la fin du processus Popen (avec des threads)

Je rencontre des problèmes lorsque j'utilise subprocess.Popen() pour générer plusieurs instances de la même application à partir de mon script python, à l'aide de threads permettant de les exécuter simultanément. Dans chaque thread, j'exécute l'application à l'aide de l'appel popen(), puis j'attends qu'elle se termine en appelantwait(). Le problème semble être que l'appel wait()- n'attend pas réellement la fin du processus. J'ai essayé d'utiliser un seul fil et d'imprimer des messages texte au début et à la fin du processus. Donc, la fonction thread ressemblerait à quelque chose comme ceci:

def worker():
    while True:
        job = q.get() # q is a global Queue of jobs
        print('Starting process %d' % job['id'])
        proc = subprocess.Popen(job['cmd'], Shell=True)
        proc.wait()
        print('Finished process %d' % job['id'])
        job.task_done()

Mais même lorsque je n'utilise qu'un seul thread, plusieurs messages "Processus de démarrage ..." sont affichés avant que le message "Processus terminé ..." ne s'affiche. Existe-t-il des cas où wait() n'attend pas réellement? J'ai plusieurs applications externes différentes (applications de console C++), qui auront à leur tour plusieurs instances s'exécutant simultanément. Pour certaines d'entre elles, mon code fonctionne, mais pas pour d'autres. Peut-il y avoir un problème avec les applications externes qui affecte d'une manière ou d'une autre l'appel à wait()? Le code pour la création des threads ressemble à ceci:

for i in range(1):
    t = Thread(target=worker)
    t.daemon = True
    t.start()
q.join() # Wait for the queue to empty

Mise à jour 1 : Je devrais également ajouter que pour certaines applications externes, je reçois parfois un code de retour (proc.returncode) de -1073471801. Par exemple, l'une des applications externes donnera ce code de retour les deux premières fois que Popen est appelé, mais pas les deux dernières (lorsque j'ai quatre tâches).

Mise à jour 2 : .__ Pour éclaircir les choses, il me reste quatre tâches en attente, qui correspondent à quatre cas de test différents. Lorsque j'exécute mon code, pour l'une des applications externes, les deux premiers appels Popen- génèrent le code retour -1073471801. Mais si j'imprime la commande exacte que Popen appelle et que je l'exécute dans une fenêtre de commande, il s'exécute sans problème.

Résolu! .__ J'ai réussi à résoudre les problèmes que je rencontrais. Je pense que le problème était mon manque d'expérience dans la programmation par thread. J'ai raté le fait que, lorsque j'avais créé mes premiers threads de travail, ils continuaient à vivre jusqu'à la fin du script python. Par erreur, j'ai créé plusieurs threads de travail chaque fois que je mettais de nouveaux éléments dans la file d'attente (je le fais par lots pour chaque programme externe que je veux exécuter). Ainsi, au moment de passer à la quatrième application externe, quatre threads s'exécutaient simultanément, même si je pensais n'en avoir qu'un. 

16
iceaway

Vous pouvez également utiliser check_call() à la place de Popen. check_call() attend la fin de la commande, même lorsque Shell=True, puis renvoie le code de sortie du travail.

11
Nick

Malheureusement, lorsque vous exécutez votre sous-processus à l'aide de Shell=True, wait() attend uniquement que le sous-processus sh se termine et non pour la commande cmd.

Je suggérerai s’il est possible de ne pas utiliser le Shell=True, sinon vous pouvez créer un groupe de processus comme dans ce answer et utiliser os.waitpid pour attendre le groupe de processus et pas seulement le Shell processus.

J'espère que c'était utile :)

9
mouad

J'avais des problèmes aussi, mais j'ai été inspiré par le vôtre.

Le mien ressemble à ceci et fonctionne à merveille:

    startupinfo = subprocess.STARTUPINFO()
    startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW
    startupinfo.wShowWindow = subprocess.SW_HIDE
    proc = subprocess.Popen(command, startupinfo=startupinfo)
    proc.communicate()
    proc.wait()

Notez que celui-ci cache également la fenêtre.

0
alfadog67

Assurez-vous que toutes les applications que vous appelez ont des codes de retour système valides à la fin

0
Chakib