web-dev-qa-db-fra.com

Appels de sous-processus bloquants et non bloquants

Je suis complètement confus entre subprocess.call(), subprocess.Popen(), subprocess.check_call().

Qui bloque et qui ne l'est pas?

Ce que je veux dire, c'est si j'utilise subprocess.Popen() si le processus parent attend que le processus enfant attende return/exit avant de poursuivre son exécution.

Comment fonctionne Shell=True affecte ces appels?

57
Roshan Mehta

Popen est non bloquant. call et check_call Bloquent. Vous pouvez créer le bloc d'instance Popen en appelant sa méthode wait ou communicate.

Si vous regardez dans le code source , vous verrez que call appelle Popen(...).wait(), c'est pourquoi il bloque. check_call Appelle call, raison pour laquelle il bloque également.

À proprement parler, Shell=True Est orthogonal à la question du blocage. Cependant, Shell=True Oblige Python à exécuter un shell, puis à exécuter la commande dans le shell. Si vous utilisez un appel bloquant, l'appel sera renvoyé lorsque Shell se termine. Comme le shell peut générer un sous-processus pour exécuter la commande, il peut se terminer avant le sous-processus généré. Par exemple,

import subprocess
import time

proc = subprocess.Popen('ls -lRa /', Shell=True)
time.sleep(3)
proc.terminate()
proc.wait()

Deux processus sont engendrés ici: Popen génère un sous-processus exécutant le shell. Le shell génère à son tour un sous-processus exécutant ls. proc.terminate() tue le shell, mais le sous-processus exécutant ls reste. (Cela se manifeste par une sortie copieuse, même après la fin du script python. Préparez-vous à tuer le ls avec pkill ls.).)

83
unutbu