2009-04-01 4 views
33

Comment puis-je appeler un programme externe avec un script python et récupérer le code de sortie et de retour?Comment appeler un programme externe en python et récupérer le code de sortie et de retour?

+2

Il existe quelques questions et réponses sur SO qui vous aideront: http://stackoverflow.com/questions/89228/how-to-call-external-command-in-python –

+0

Possible duplicate de [Appel d'une commande externe en Python] (http://stackoverflow.com/questions/89228/calling-an-external-command-in-python) –

Répondre

45

Regardez le module subprocess: un exemple simple ...

from subprocess import Popen, PIPE 

process = Popen(["ls", "-la", "."], stdout=PIPE) 
(output, err) = process.communicate() 
exit_code = process.wait() 
+10

J'ai modifié la réponse ci-dessus pour refléter la suggestion d'Ambroz au cas où quelqu'un le ferait pas lu les commentaires et utilise le code précédemment incorrect. –

+0

si cela ne fonctionne pas pour une raison quelconque, vous pouvez ajouter shell = True aux paramètres (dans les fenêtres?) – ntg

+0

Il semble que [la solution ci-dessus] (https://stackoverflow.com/a/707001/1321680) peut être remplacé par un simple appel ['subprocess.run()'] (https://docs.python.org/dev/library/subprocess.html#subprocess.run) (Python> = 3.5 est requis). –

13

Après commentaire précédent Ambroz Bizjak, voici une solution qui a fonctionné pour moi:

import shlex 
from subprocess import Popen, PIPE 

cmd = "..." 
process = Popen(shlex.split(cmd), stdout=PIPE) 
process.communicate() 
exit_code = process.wait() 
+3

C'est de loin la meilleure réponse. – dotancohen

+3

J'ai un post similaire [ici] (https://stackoverflow.com/questions/1996518/retrieving-the-output-of-subprocess-call/21000308#21000308) qui montre comment obtenir trois choses à partir d'un processus: exitcode , stdout, stderr. – Jabba

2

Après quelques recherches, j'ai le code suivant qui fonctionne très bien pour moi. Il imprime à la fois stdout et stderr en temps réel. J'espère que cela aidera quelqu'un d'autre qui en a besoin.

stdout_result = 1 
stderr_result = 1 


def stdout_thread(pipe): 
    global stdout_result 
    while True: 
     out = pipe.stdout.read(1) 
     stdout_result = pipe.poll() 
     if out == '' and stdout_result is not None: 
      break 

     if out != '': 
      sys.stdout.write(out) 
      sys.stdout.flush() 


def stderr_thread(pipe): 
    global stderr_result 
    while True: 
     err = pipe.stderr.read(1) 
     stderr_result = pipe.poll() 
     if err == '' and stderr_result is not None: 
      break 

     if err != '': 
      sys.stdout.write(err) 
      sys.stdout.flush() 


def exec_command(command, cwd=None): 
    if cwd is not None: 
     print '[' + ' '.join(command) + '] in ' + cwd 
    else: 
     print '[' + ' '.join(command) + ']' 

    p = subprocess.Popen(
     command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd 
    ) 

    out_thread = threading.Thread(name='stdout_thread', target=stdout_thread, args=(p,)) 
    err_thread = threading.Thread(name='stderr_thread', target=stderr_thread, args=(p,)) 

    err_thread.start() 
    out_thread.start() 

    out_thread.join() 
    err_thread.join() 

    return stdout_result + stderr_result 
3

J'ai développé une petite bibliothèque (py-execute) qui vous permet d'exécuter des programmes externes, permet de récupérer la sortie et la retcode et, en même temps obtenir une sortie dans la console en temps réel:

>>> from py_execute.process_executor import execute 
>>> ret = execute('echo "Hello"') 
Hello 
>>> ret 
(0, 'Hello\n') 

Vous pouvez éviter d'imprimer à la console passant une user_io maquette:

>>> from mock import Mock 
>>> execute('echo "Hello"', ui=Mock()) 
(0, 'Hello\n') 

je l'ai écrit parce qu'avec plaine Popen (en Python 2.7) J'avais du mal à exécuter comm ets avec une sortie longue

Questions connexes