> Modules standards > Autres modules > Lancement de process
Lancement de process
La nouvelle méthode de haut niveau est run :
- cp = subprocess.run(['ls', '-ls']) : appel système avec la liste des arguments, le stdout et le stderr du programme appelé sont redirigés vers celui du script python. Renvoie un object subprocess.CompletedProcess.
- cp = subprocess.run(['ls', '-ls'], capture_output = True, text = True) : cp.stdout renvoie du texte, pas des bytes.
- cp.returncode : statut de retour du process.
- cp.check_returncode() : vérifie le statut de retour et produit une exception s'il est différent de 0.
- subprocess.run(['ls', '-ls'], check = True) : si le statut de sortie est différent de 0, lance une exxception (défaut est check = False).
- subprocess.run(['ls -ls', shell = True) : permet de passer directement une commande shell.
- cp = subprocess.run('ls -ls', shell = True, check = True, capture_output = True) : permet de récupérer à la fois le stdout et le stderr dans cp.stdout et cp.stderr : ce sont des bytes.
- cp = subprocess.run('ls -ls', shell = True, check = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE): équivalent, mais permet de le faire pour l'un et pas pour l'autre.
- cp = subprocess.run('ls -ls', shell = True, check = True, stdout = subprocess.PIPE, text = True) : on récupère dans cp.stdout une string plutôt que des bytes.
Comment lancer un commande avec un pipe tout en vérifiant que tout s'est bien passé ?
- quand on lance une commande avec un pipe, le statut de retour est celui de la dernière commande : ls -zz|at ; echo $? donne 0 !
- on peut éviter ce comportement en bash avec set -o pipefail : ne retourne un statut 0 que si tous les programmes sont sortis en statut 0, et c'est spécifique bash, pas sh.
- mais les appels systèmes python utilisent sh par défaut, et non bash ...
- solution : cp = subprocess.run('set -o pipefail ; ls -zz|cat', shell = True, executable = 'bash', check = True, text = True) : lance une exception comme attendu, alors que sans le set -o pipefail, aucune exception n'est produite !
Si on veut lancer une commande dont on veut récupérer le stdout et le stderr même si l'exécution s'est mal passée :
popen = subprocess.Popen(myCommand, shell = True, stdin = None, stdout = subprocess.PIPE, stderr = subprocess.PIPE, encoding = 'utf8'); (out, err) = popen.communicate()
on peut alors avoir le code de sortie avec popen.returncode pour vérifier s'il est à 0 ou non.
Le paramètre encoding est nécessaire si on veut récupérer des strings, sinon, ce sont des bytes par défaut.
Pour lancer une commande et lire l'output immédiatement au fur et à mesure :
myPopen = subprocess.Popen(com, shell = True, stdout = subprocess.PIPE, encoding = 'ascii')
while True:
line = myPopen.stdout.readline()
if line == '' and myPopen.poll() is not None:
break
...
returnStatus = myPopen.poll()
if returnStatus != 0:
raise RuntimeError('Problem')
Pour lancer une commande qui génère un tableau et lire l'output au fur et à mesure :
popen = subprocess.Popen('samtools view ' + bamFile, stdout = subprocess.PIPE, shell = True, encoding = 'utf8')
reader = csv.reader(popen.stdout, delimiter = '\t')
for line in reader:
...
popen.wait()
if popen.returncode != 0:
raise RuntimeError('Error')
Appel système général avec Popen, bloquant ou non-bloquant :
Copyright python-simple.com
programmer en python, tutoriel python, graphes en python, Aymeric Duclert