La risposta a questa domanda dipende dalla versione di Python che stai utilizzando. L'approccio più semplice è utilizzare la subprocess.check_outputfunzione:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_outputesegue un singolo programma che accetta solo argomenti come input. 1 Restituisce il risultato esattamente come stampato stdout. Se è necessario scrivere input su stdin, andare avanti alle sezioni runo Popen. Se si desidera eseguire comandi di shell complessi, vedere la nota shell=Truealla fine di questa risposta.
La check_outputfunzione funziona su quasi tutte le versioni di Python ancora ampiamente utilizzate (2.7+). 2 Ma per le versioni più recenti, non è più l'approccio consigliato.
Versioni moderne di Python (3.5 o successive): run
Se si utilizza Python 3.5 o versioni successive e non è necessaria la compatibilità con le versioni precedenti , si consiglia la nuova runfunzione . Fornisce un'API di alto livello molto generale per il subprocessmodulo. Per acquisire l'output di un programma, passare il subprocess.PIPEflag stdoutall'argomento della parola chiave. Quindi accedere stdoutall'attributo CompletedProcessdell'oggetto restituito :
>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Il valore restituito è un bytesoggetto, quindi se si desidera una stringa corretta, è necessario decode. Supponendo che il processo chiamato restituisca una stringa con codifica UTF-8:
>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Tutto questo può essere compresso in un unico liner:
>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Se si desidera passare l'input al processo stdin, passare un bytesoggetto inputall'argomento della parola chiave:
>>> cmd = ['awk', 'length($0) > 5']
>>> input = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=input)
>>> result.stdout.decode('utf-8')
'foofoo\n'
È possibile acquisire errori passando stderr=subprocess.PIPE(acquisisci in result.stderr) o stderr=subprocess.STDOUT(acquisisci result.stdoutinsieme all'output normale). Quando la sicurezza non è un problema, è anche possibile eseguire comandi di shell più complessi passando shell=Truecome descritto nelle note di seguito.
Questo aggiunge solo un po 'di complessità, rispetto al vecchio modo di fare le cose. Ma penso che valga la pena pagare: ora puoi fare quasi tutto ciò che devi fare con la runsola funzione.
Versioni precedenti di Python (2.7-3.4): check_output
Se stai usando una versione precedente di Python o hai bisogno di una modesta compatibilità con le versioni precedenti, puoi probabilmente usare la check_outputfunzione come brevemente descritto sopra. È disponibile da Python 2.7.
subprocess.check_output(*popenargs, **kwargs)
Prende gli stessi argomenti di Popen(vedi sotto) e restituisce una stringa contenente l'output del programma. L'inizio di questa risposta ha un esempio di utilizzo più dettagliato. In Python 3.5 e versioni successive, check_outputequivale a eseguire runcon check=Truee stdout=PIPEe restituire solo l' stdoutattributo.
Puoi passare stderr=subprocess.STDOUTper assicurarti che i messaggi di errore siano inclusi nell'output restituito, ma in alcune versioni di Python il passaggio stderr=subprocess.PIPEa check_outputpuò causare deadlock . Quando la sicurezza non è un problema, è anche possibile eseguire comandi di shell più complessi passando shell=Truecome descritto nelle note di seguito.
Se è necessario eseguire il pipe stderro passare l'input al processo, check_outputnon sarà all'altezza dell'attività. Vedi gli Popenesempi seguenti in quel caso.
Applicazioni complesse e versioni legacy di Python (2.6 e precedenti): Popen
Se hai bisogno di una profonda compatibilità con le versioni precedenti o se hai bisogno di funzionalità più sofisticate di quelle check_outputfornite, dovrai lavorare direttamente con gli Popenoggetti, che incapsulano l'API di basso livello per i sottoprocessi.
Il Popencostruttore accetta un singolo comando senza argomenti o un elenco contenente un comando come primo elemento, seguito da un numero qualsiasi di argomenti, ciascuno come elemento separato nell'elenco. shlex.splitpuò aiutare ad analizzare le stringhe in elenchi formattati in modo appropriato. Popengli oggetti accettano anche una serie di argomenti diversi per la gestione dell'IO processo e la configurazione di basso livello.
Per inviare input e acquisire output, communicateè quasi sempre il metodo preferito. Come in:
output = subprocess.Popen(["mycmd", "myarg"],
stdout=subprocess.PIPE).communicate()[0]
O
>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
Se impostato stdin=PIPE, communicateconsente anche di passare i dati al processo tramite stdin:
>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo
Nota La risposta di Aaron Hall , che indica che su alcuni sistemi, potrebbe essere necessario insieme stdout, stderre stdintutti a PIPE(o DEVNULL) per arrivare communicatea lavoro a tutti.
In alcuni rari casi, potrebbe essere necessario acquisire output complessi e in tempo reale. La risposta di Vartec suggerisce una via da seguire, ma metodi diversi da quelli communicatesoggetti a deadlock se non utilizzati con attenzione.
Come per tutte le funzioni di cui sopra, quando la sicurezza non è un problema, è possibile eseguire comandi di shell più complessi passando shell=True.
Appunti
1. Esecuzione dei comandi shell: l' shell=Trueargomento
Normalmente, ogni chiamata a run, check_outputo il Popencostruttore esegue un singolo programma . Ciò significa che non ci sono pipe eleganti in stile bash. Se si desidera eseguire comandi shell complessi, è possibile passare shell=True, che supportano tutte e tre le funzioni.
Tuttavia, ciò solleva problemi di sicurezza . Se stai facendo qualcosa di più di uno script leggero, potresti fare meglio a chiamare ciascun processo separatamente e passare l'output da ciascuno come input al successivo, tramite
run(cmd, [stdout=etc...], input=other_output)
O
Popen(cmd, [stdout=etc...]).communicate(other_output)
La tentazione di collegare direttamente i tubi è forte; resistergli. Altrimenti, probabilmente vedrai deadlock o dovrai fare cose bizzarre come questa .
2. Considerazioni su Unicode
check_outputrestituisce una stringa in Python 2, ma un bytesoggetto in Python 3. Vale la pena dedicare un momento a conoscere unicode se non l'hai già fatto.