2010-03-23 15 views
205

Sto provando a effettuare una chiamata di sistema in Python e memorizzare l'output in una stringa che posso manipolare nel programma Python.Memorizza l'output del sottoprocesso. Chiamata in attesa in una stringa

#!/usr/bin/python 
import subprocess 
p2 = subprocess.Popen("ntpq -p") 

Ho provato un paio di cose tra cui alcuni dei suggerimenti qui:

Retrieving the output of subprocess.call()

ma senza alcuna fortuna.

+1

È sempre utile postare il codice effettivamente eseguito e il traceback effettivo o bahaviour inatteso per domande concrete come questa. Ad esempio, non so cosa hai provato a fare per ottenere l'output e ho il sospetto che in realtà non sei arrivato così lontano per iniziare - avresti avuto un errore nel non trovare il file per "" ntpq -p "' , che è una parte diversa del problema di quanto tu stia chiedendo. –

risposta

356

In Python 2.7 o Python 3

Invece di fare direttamente un oggetto Popen, è possibile utilizzare il subprocess.check_output() function memorizzare l'output di un comando in una stringa:

from subprocess import check_output 
out = check_output(["ntpq", "-p"]) 

In Python 2.4 -2,6

Utilizzare il metodo communicate.

import subprocess 
p = subprocess.Popen(["ntpq", "-p"], stdout=subprocess.PIPE) 
out, err = p.communicate() 

out è quello che vuoi.

Nota importante circa le altre risposte

Nota come ho passato nel comando. L'esempio "ntpq -p" mostra un'altra questione. Poiché Popen non richiama la shell, si utilizzerà un elenco di comandi e opzioni, ["ntpq", "-p"].

+2

In questo caso, python attende che questa chiamata di sistema termini? O è necessario chiamare esplicitamente la funzione wait/waitpid? – NoneType

+5

@NoneType, 'Popen.communicate' non ritorna fino al termine del processo. –

+8

se si desidera ottenere errore flusso aggiungere stderr: 'p = subprocess.Popen ([" ntpq "," -p "], stdout = subprocess.PIPE, stderr = subprocess.PIPE) ' – Tim

32

questo ha lavorato per me per reindirizzare stdout (stderr può essere gestita in modo simile):

from subprocess import Popen, PIPE 
pipe = Popen(path, stdout=PIPE) 
text = pipe.communicate()[0] 

Se non funziona per voi, si prega di specificare esattamente il problema che stai avendo.

+3

Questo produce un oggetto strano. Quando lo converto in stringa, sfugge agli spazi bianchi come '\ n'. –

19

Supponendo che pwd è solo un esempio, questo è come si può fare:

import subprocess 

p = subprocess.Popen("pwd", stdout=subprocess.PIPE) 
result = p.communicate()[0] 
print result 

Vedere la subprocess documentation per another example e ulteriori informazioni.

4
import os 
list = os.popen('pwd').read() 

In questo caso sarà presente un solo elemento nell'elenco.

+5

'os.popen' è deprecato a favore del modulo' subprocess'. –

+2

Questo è stato abbastanza utile per l'amministratore su una vecchia scatola che utilizza la serie 2.2.X di Python. –

15

subprocess.Popen: http://docs.python.org/2/library/subprocess.html#subprocess.Popen

import subprocess 

command = "ntpq -p" # the shell command 
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None, shell=True) 

#Launch the shell command: 
output = process.communicate() 

print output[0] 

Nel costruttore Popen, se guscio è vero, si dovrebbe passare il comando come una stringa piuttosto che come una sequenza. In caso contrario, basta dividere il comando in una lista:

command = ["ntpq", "-p"] # the shell command 
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None) 

Se avete bisogno di leggere anche l'errore standard, nel l'inizializzazione Popen, è possibile impostare stderr-sottoprocesso.PIPE o per subprocess.STDOUT:

import subprocess 

command = "ntpq -p" # the shell command 
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) 

#Launch the shell command: 
output, error = process.communicate() 
+0

+1 per l'argomento shell –

3

Ho scritto una piccola funzione in base alle altre risposte qui:

def pexec(*args): 
    return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0].rstrip() 

Usage:

changeset = pexec('hg','id','--id') 
branch = pexec('hg','id','--branch') 
revnum = pexec('hg','id','--num') 
print('%s : %s (%s)' % (revnum, changeset, branch)) 
10

Questo funziona perfettamente per me :

import subprocess 
try: 
    #prints results and merges stdout and std 
    result = subprocess.check_output("echo %USERNAME%", stderr=subprocess.STDOUT, shell=True) 
    print result 
    #causes error and merges stdout and stderr 
    result = subprocess.check_output("copy testfds", stderr=subprocess.STDOUT, shell=True) 
except subprocess.CalledProcessError, ex: # error code <> 0 
    print "--------error------" 
    print ex.cmd 
    print ex.message 
    print ex.returncode 
    print ex.output # contains stdout and stderr together 
3

Questo è stato perfetto per me. Si otterrà il codice di ritorno, stdout e stderr in una tupla.

from subprocess import Popen, PIPE 

def console(cmd): 
    p = Popen(cmd, shell=True, stdout=PIPE) 
    out, err = p.communicate() 
    return (p.returncode, out, err) 

Per esempio:

result = console('ls -l') 
print 'returncode: %s' % result[0] 
print 'output: %s' % result[1] 
print 'error: %s' % result[2] 
7

per Python 2.7+ la risposta idiomatica è quello di utilizzare subprocess.check_output()

Si dovrebbe inoltre notare la gestione di argomenti quando si invoca un sottoprocesso, in quanto si può essere un po 'di confusione ....

Se args è solo un singolo comando senza argomenti propri (o si ha shell=True impostato), può essere una stringa. Altrimenti deve essere una lista.

per esempio ... per richiamare il comando ls, questo va bene:

from subprocess import check_call 
check_call('ls') 

modo è questo:

from subprocess import check_call 
check_call(['ls',]) 

tuttavia, se si desidera passare alcuni argomenti per il comando di shell , si non si può fare questo:

from subprocess import check_call 
check_call('ls -al') 

ins tead, si deve passare come un elenco:

from subprocess import check_call 
check_call(['ls', '-al']) 

la funzione shlex.split() a volte può essere utile per dividere una stringa in sintassi di conchiglia, prima di creare un sottoprocessi ... come questo:

from subprocess import check_call 
import shlex 
check_call(shlex.split('ls -al')) 
+0

Cinque anni dopo, questa domanda sta ancora ottenendo molto amore. Grazie per l'aggiornamento 2.7+, Corey! – Mark

Problemi correlati