2008-11-28 19 views
40

J'ai un script python qui doit lancer une commande shell pour chaque fichier dans un répertoire:Lancer une commande shell avec un script python, attendez la fin et revenir au script

import os 

files = os.listdir(".") 
for f in files: 
    os.execlp("myscript", "myscript", f) 

Cette fonctionne bien pour le premier fichier, mais après la fin de la commande "myscript", l'exécution s'arrête et ne revient pas au script python.

Comment puis-je faire? Dois-je fork() avant calling os.execlp()?

+0

[ 'returnCode = subprocess.call ([ 'myscript', f])'] (http://stackoverflow.com/a/5184921/4279) – jfs

Répondre

72

subprocess: The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes.

http://docs.python.org/library/subprocess.html

Utilisation:

import subprocess 
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) 
process.wait() 
print process.returncode 
+1

Je pense que la réponse acceptée, cela devrait contenir au moins la même quantité de détails que @Harley. Ceci est plus d'une demande personnelle, mais je pense que les nouveaux docs présentent mieux l'information. Pourriez-vous lier à la version 2.7 de la documentation à la place? –

+3

La nouvelle version de la documentation se trouve à l'adresse http://docs.python.org/library/subprocess.html. – wanderso

+3

remove stdout = PIPE il peut bloquer le script si le programme enfant produit suffisamment de sortie (environ 65 Ko sur Linux). 'shell = True' est inutile. – jfs

7

Les fonctions remplacent le programme en cours par le nouveau. Lorsque ce programme se termine, votre processus aussi. Vous voulez probablement os.system().

+1

os.system() est très problématique en termes de sécurité, au point où de nombreuses bibliothèques C suppriment purement et simplement cette fonction C standard. subprocess.Popen() avec shell = Faux devrait être utilisé à la place – Shnatsel

3

utilisation spawn

import os 
os.spawnlp(os.P_WAIT, 'cp', 'cp', 'index.html', '/dev/null') 
50

Vous pouvez utiliser subprocess.Popen. Il y a quelques façons de le faire:

import subprocess 
cmd = ['/run/myscript', '--arg', 'value'] 
p = subprocess.Popen(cmd, stdout=subprocess.PIPE) 
for line in p.stdout: 
    print line 
p.wait() 
print p.returncode 

Ou, si vous ne faites pas ce que le programme externe ne fait:

cmd = ['/run/myscript', '--arg', 'value'] 
subprocess.Popen(cmd).wait() 
+0

'pour line dans p.stdout:' peut retarder la sortie d'une ligne en raison de la lecture anticipée. Vous pouvez utiliser 'pour line dans iter (p.stdout.readline, b ''): print line,' (note: virgule à la fin). Enlevez stdout = PIPE dans le deuxième exemple; ça pourrait accrocher le script. Ou utilisez juste 'subprocess.call()' si vous n'avez pas besoin d'une exception pour le code retourné non nul – jfs

11

Le module subprocess est venu le long chemin depuis 2008. En particulier check_call et check_output simplifier encore plus les tâches de sous-processus simples. La famille de fonctions check_* est gentille, car elle déclenche une exception si quelque chose ne va pas.

import os 
import subprocess 

files = os.listdir('.') 
for f in files: 
    subprocess.check_call([ 'myscript', f ]) 

Toute sortie générée par myscript affiche comme si votre processus produit la sortie (techniquement myscript et votre part de script python le même stdout). Il y a plusieurs façons d'éviter cela.

  • check_call([ 'myscript', f ], stdout=subprocess.PIPE)
    Le stdout sera supressed (méfiez-vous si myscript produit plus que 4k de la production). stderr sera toujours affiché sauf si vous ajoutez l'option stderr=subprocess.PIPE.
  • check_output([ 'myscript', f ])
    check_output renvoie la sortie stdout sous la forme d'une chaîne, de sorte qu'elle n'est pas affichée. stderr est toujours affiché sauf si vous ajoutez l'option stderr=subprocess.STDOUT.
+0

Merci pour la mise à jour utile. –

+0

Qu'est-ce que cela rend plus facile? –

+2

@Luke Stanley: votre question n'est pas claire, mais je vais essayer. Les fonctions 'subprocess.check_ *' facilitent l'appel des binaires externes plutôt que l'utilisation manuelle de 'subprocess.Popen'. En particulier, vous n'avez jamais à faire face à 'wait()', 'communicate()', 'return_code', etc. Vous n'avez pas non plus besoin de vous soucier de gotchas comme le tuyau suspendu bloquant l'exécutable. Quand il s'agit de _interacting_ avec un binaire externe, les fonctions 'check_ *' ne sont pas très utiles, mais pour la plupart des cas d'utilisation, le résultat est plus court et moins sujette aux erreurs, c'est-à-dire plus facile. –

0

J'utilise os.system

import os 
os.system("pdftoppm -png {} {}".format(path2pdf, os.path.join(tmpdirname, "temp"))) 
Questions connexes