2008-12-11 13 views
16

Je voudrais exécuter plusieurs commandes consécutives:Exécuter des commandes Séquentiellement en Python

ie (juste pour illustrer mes besoins):

cmd (la coquille)

puis

cd dir

et

ls

et lire le résultat des ls.

Une idée avec un module de sous-processus?

MISE À JOUR:

cd dir et ls sont juste un exemple. J'ai besoin d'exécuter des commandes complexes (en suivant un ordre particulier, sans aucun pipeline). En fait, je voudrais un shell de sous-processus et la possibilité de lancer de nombreuses commandes dessus.

+3

peut-être vous devriez écrire un script shell au lieu d'un script python – hop

Répondre

19

Il existe un moyen facile d'exécuter une séquence de commandes.

Utilisez les éléments suivants dans subprocess.Popen

"command1; command2; command3" 

Ou, si vous êtes coincé avec des fenêtres, vous avez plusieurs choix.

  • Créer un fichier « .bat » temporaire et fournir ce à subprocess.Popen

  • Créer une séquence de commandes avec « \ n » séparateurs dans une seule chaîne longue.

Utilisez "" "s, comme celui-ci.

""" 
command1 
command2 
command3 
""" 

Ou, si vous devez faire des choses au coup par coup, vous devez faire quelque chose comme ça.

class Command(object): 
    def __init__(self, text): 
     self.text = text 
    def execute(self): 
     self.proc= subprocess.Popen(... self.text ...) 
     self.proc.wait() 

class CommandSequence(Command): 
    def __init__(self, *steps): 
     self.steps = steps 
    def execute(self): 
     for s in self.steps: 
      s.execute() 

Cela permettra vous pour construire une séquence de commandes

+2

'subprocess.Popen ("ls")' des travaux. Cependant, 'subprocess.Popen (" ls; ls ")' échoue pour moi. Erreur: 'retraçage (appel le plus récent en dernier): Fichier "", ligne 1, dans Fichier "/usr/lib64/python2.6/subprocess.py", ligne 639, dans __init__ errread, ERRECRIT) fichier "/usr/lib64/python2.6/subprocess.py", ligne 1228, à _execute_child augmentation child_exception OSError: [Errno 2] Aucun fichier ou directory' –

+0

Cela a échoué parce que Popen attend une liste comme premier argument et juste "ls" est équivalent à ["ls"]. Il essaie de trouver un exécutable avec le nom "ls; ls" qui n'est évidemment pas là. –

+0

L'exécution à partir de la classe CommandSequence ne passerait-elle pas par la classe execute() de la classe Command? Si oui, alors comment fonctionne s.execute? – user97662

2

Oui, la fonction subprocess.Popen() prend en charge un argument de mot-clé cwd, avec lequel vous pouvez définir le répertoire dans lequel il exécute le processus.

Je suppose que la première étape, la coquille, n'est pas nécessaire, si tout ce que vous voulez est Pour exécuter ls, il n'est pas nécessaire de l'exécuter via un shell.

Bien sûr, vous pouvez également simplement passer le répertoire souhaité en tant qu'argument à ls.

Mise à jour: il peut être intéressant de noter que pour les shells typiques, cd est implémenté dans le shell lui-même, il ne s'agit pas d'une commande externe sur le disque. C'est parce qu'il doit changer le répertoire courant du processus, qui doit être fait à partir du processus. Puisque les commandes s'exécutent en tant qu'enfant traité, généré par le shell, elles ne peuvent pas le faire.

1

'bar' Trouver dans tous les fichiers dont le nom contient 'foo':

from subprocess import Popen, PIPE 
find_process = Popen(['find', '-iname', '*foo*'], stdout=PIPE) 
grep_process = Popen(['xargs', 'grep', 'bar'], stdin=find_process.stdout, stdout=PIPE) 
out, err = grep_process.communicate() 

'out' et 'err' sont des objets de chaîne contenant la sortie standard et, éventuellement, la sortie d'erreur.

21

Pour ce faire, vous devez:

  • fournissent l'argument shell=True dans le subprocess.Popen appel, et
  • séparer les commandes avec:
    • ; si on travaille sous une coque * nix (bash, cendres, sh, ksh, csh, tcsh, zsh etc.)
    • & si vous utilisez sous la cmd.exe de Windows
+1

Ou pour les fenêtres, vous pouvez utiliser && pour qu'une commande qui provoque des erreurs empêche l'exécution des commandes après elle. – twasbrillig

+0

@twasbrillig Intéressant; Je ne savais pas que cmd.exe partageait ce séparateur de commandes avec des shells Unix. Je devrais mettre à jour mes connaissances. Merci! – tzot

+0

Merci, c'est inestimable et était vraiment difficile à trouver. – CodeMonkey

-1

ci-dessous script python ont 3 fonction ce que vous excute juste Je suis allé:

import sys 
import subprocess 

def cd(self,line): 
    proc1 = subprocess.Popen(['cd'],stdin=subprocess.PIPE) 
    proc1.communicate() 

def ls(self,line): 
    proc2 = subprocess.Popen(['ls','-l'],stdin=subprocess.PIPE) 
    proc2.communicate() 

def dir(silf,line): 
    proc3 = subprocess.Popen(['cd',args],stdin=subprocess.PIPE) 
    proc3.communicate(sys.argv[1]) 
+0

c'est incorrect. 'cd' n'a aucun effet sur le parent et il est probable que OP veuille incorporer la commande shell (' Popen() 'n'exécute pas le shell à moins que vous ne le demandiez explicitement - bien que cela n'aidera pas dans ce cas). – jfs

Questions connexes