2010-08-17 9 views
173

Desidero assegnare l'output di un comando eseguito utilizzando os.system a una variabile e impedisco che venga trasmesso allo schermo. Ma, nel codice sottostante, l'output viene inviato allo schermo e il valore stampato per var è 0, che suppongo significhi se il comando è stato eseguito correttamente o meno. C'è un modo per assegnare l'output del comando alla variabile e anche impedirne la visualizzazione sullo schermo?Assegnare l'output di os.system a una variabile e impedirne la visualizzazione sullo schermo

var = os.system("cat /etc/services") 
print var #Prints 0 
+2

possibile duplicato di [equivalente di backtick in Python] (http://stackoverflow.com/questions/1410976/equivalent-of-backticks-in-python) – msw

+3

Non utilizzare 'os.system' (né 'os.popen', per la risposta che hai accettato): usa' subprocess.Popen', è _way_ better! –

+1

@AlexMartelli, non è possibile utilizzare un comando complesso (ad esempio piped) nel sottoprocesso.Popen(), ma con os.system uno può – vak

risposta

256

Da "Equivalent of Bash Backticks in Python", che ho chiesto molto tempo fa, quello che si consiglia di utilizzare è popen:

os.popen('cat /etc/services').read() 

Dal docs for Python 3.6,

Questo viene implementato utilizzando subprocess.Popen; vedere la documentazione della classe per metodi più potenti per gestire e comunicare con i sottoprocessi .


Ecco il codice corrispondente subprocess:

import subprocess 

proc = subprocess.Popen(["cat", "/etc/services"], stdout=subprocess.PIPE, shell=True) 
(out, err) = proc.communicate() 
print "program output:", out 
+0

+1, ottima soluzione, grazie. –

+6

Si noti che la soluzione 'subprocess.check_output' di Walter è più vicina alla one-liner Pythonic che sembra si stia cercando, purché non ci si preoccupi di' stderr'. – chbrown

+7

@ChrisBunch Perché suprocess è una soluzione migliore di 'os.popen'? –

40

Il modulo comandi è un modo ragionevolmente alto livello per effettuare questa operazione:

import commands 
status, output = commands.getstatusoutput("cat /etc/services") 

stato è 0, l'uscita è il contenuto di/etc/services.

+30

Citazione dalla [documentazione del modulo comandi] (http://docs.python.org/2 /library/commands.html#commands): * "Deprecato dalla versione 2.6: il modulo dei comandi è stato rimosso in Python 3. Usa invece il modulo subprocess. "*. –

+4

sicuro che è obsoleto, ma a volte si vuole solo ottenere qualcosa fatto rapidamente e facilmente in poche righe di codice. – anon58192932

+4

@advocate controlla il comando check_output del sottoprocesso. È veloce, facile e non si svaluterà presto! –

127

Si potrebbe anche voler esaminare il modulo subprocess, che è stato costruito per sostituire l'intera famiglia di Python popen chiamate di tipo.

import subprocess 
output = subprocess.check_output("cat /etc/services", shell=True) 

Il vantaggio che ha è che c'è un sacco di flessibilità con il modo si richiama comandi, in cui sono collegati gli standard nei corsi d'acqua/out/errore, ecc

+2

nota, 'check_output' è stato aggiunto con python 2.7 https://docs.python.org/2.7/library/subprocess.html#subprocess.check_output – phyatt

16

So che questo è già stato risposto , ma ho voluto condividere un modo potenzialmente più bello chiamare popen attraverso l'uso di from x import x e funzioni:

from subprocess import PIPE, Popen 


def cmdline(command): 
    process = Popen(
     args=command, 
     stdout=PIPE, 
     shell=True 
    ) 
    return process.communicate()[0] 

print cmdline("cat /etc/services") 
print cmdline('ls') 
print cmdline('rpm -qa | grep "php"') 
print cmdline('nslookup google.com') 
+0

3 anni dopo, questo è ciò che ha funzionato per me. L'ho buttato in un file separato chiamato 'cmd.py', e poi nel mio file principale ho scritto' da cmd import cmdline' e l'ho usato come necessario. –

1

lo faccio con il file os.system temp:

import tempfile,os 
def readcmd(cmd): 
    ftmp = tempfile.NamedTemporaryFile(suffix='.out', prefix='tmp', delete=False) 
    fpath = ftmp.name 
    if os.name=="nt": 
     fpath = fpath.replace("/","\\") # forwin 
    ftmp.close() 
    os.system(cmd + " > " + fpath) 
    data = "" 
    with open(fpath, 'r') as file: 
     data = file.read() 
     file.close() 
    os.remove(fpath) 
    return data 
4

Per python 3.5+ si consiglia di utilizzare run function from the subprocess module. Restituisce un oggetto CompletedProcess, da cui è possibile ottenere facilmente l'output e il codice di ritorno. Poiché ti interessa solo l'output, puoi scrivere un wrapper di utilità come questo.

from subprocess import PIPE, run 

def out(command): 
    result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True) 
    return result.stdout 

my_output = out("echo hello world") 
# Or 
my_output = out(["echo", "hello world"]) 
1

Python 2.6 e 3 in particolare dicono di evitare l'uso di PIPE per stdout e stderr.

il modo corretto è

import subprocess 

# must create a file object to store the output. Here we are getting 
# the ssid we are connected to 
outfile = open('/tmp/ssid', 'w'); 
status = subprocess.Popen(["iwgetid"], bufsize=0, stdout=outfile) 
outfile.close() 

# now operate on the file 
-3

Molte grazie per le risposte, molto utile. Ma non è sufficiente per ricevere risposta da un server http nel mio caso Quindi, ho aggiunto un "while" con un timeout, ad esempio 30s, dopo che la richiesta è stata eseguita dal sistema: blocca il programma e attende la risposta http e non solo il risultato della chiamata di sistema. Forse strano ma funziona!

import subprocess 

# create a file object to store the output : tmp/tempfile. 
cmd = "curl -X POST --data-urlencode \"parameter=" + someparametervalue + "\" http://localhost/reponse.php" 
outfile = open('tmp/tempfile', 'w'); 
status = subprocess.Popen(cmd, bufsize=0, stdout=outfile) 
outfile.close() 

# wait for outfile really contains something : the response of the http server 
infile = open('tmp/tempfile', 'r'); 
starttime = datetime.utcnow() 
data='' 
timeout=False 
while data=='' and not timeout: 
    data=infile.read() 
    timeout=(datetime.utcnow()-starttime).total_seconds()>30 
infile.close() 

# now operate on received data 
+2

Questo non è giusto. Non hai aspettato che il sottoprocesso si interrompesse e così stai saltando i cerchi per aggirare quel bug. Vedi https://docs.python.org/2/library/subprocess.html#popen-objects –

Problemi correlati