A resposta a esta pergunta depende da versão do Python que você está usando. A abordagem mais simples é usar a subprocess.check_outputfunção:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_outputexecuta um único programa que recebe apenas argumentos como entrada. 1 Retorna o resultado exatamente como impresso stdout. Se você precisar escrever uma entrada stdin, pule para as seções runou Popen. Se você deseja executar comandos shell complexos, consulte a nota shell=Trueno final desta resposta.
A check_outputfunção funciona em quase todas as versões do Python ainda em uso amplo (2.7+). 2 Mas para versões mais recentes, não é mais a abordagem recomendada.
Versões modernas do Python (3.5 ou superior): run
Se você estiver usando o Python 3.5 ou superior e não precisar de compatibilidade com versões anteriores , a nova runfunção é recomendada. Ele fornece uma API de alto nível muito geral para o subprocessmódulo. Para capturar a saída de um programa, passe o subprocess.PIPEsinalizador para o stdoutargumento de palavra - chave. Em seguida, acesse o stdoutatributo do CompletedProcessobjeto retornado :
>>> 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'
O valor de retorno é um bytesobjeto; portanto, se você deseja uma sequência adequada, precisará decodedisso. Supondo que o processo chamado retorne uma sequência codificada em UTF-8:
>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Tudo isso pode ser compactado em uma linha:
>>> 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 você deseja passar a entrada para o processo stdin, passe um bytesobjeto para o inputargumento de palavra - chave:
>>> 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'
Você pode capturar erros passando stderr=subprocess.PIPE(capturar para result.stderr) ou stderr=subprocess.STDOUT(capturar para result.stdoutjunto com a saída regular). Quando a segurança não é uma preocupação, você também pode executar comandos shell mais complexos, passando shell=Trueconforme descrito nas notas abaixo.
Isso adiciona um pouco de complexidade, comparado à maneira antiga de fazer as coisas. Mas acho que vale a pena: agora você pode fazer quase tudo o que precisa fazer apenas com a runfunção.
Versões anteriores do Python (2.7-3.4): check_output
Se você estiver usando uma versão mais antiga do Python, ou precisar de uma modesta compatibilidade com versões anteriores, provavelmente poderá usar a check_outputfunção conforme descrito brevemente acima. Está disponível desde o Python 2.7.
subprocess.check_output(*popenargs, **kwargs)
Ele usa os mesmos argumentos que Popen(veja abaixo) e retorna uma string contendo a saída do programa. O início desta resposta tem um exemplo de uso mais detalhado. No Python 3.5 e superior, check_outputé equivalente a executar runcom check=Truee stdout=PIPE, e retornar apenas o stdoutatributo.
Você pode transmitir stderr=subprocess.STDOUTpara garantir que as mensagens de erro sejam incluídas na saída retornada - mas, em algumas versões do Python, a passagem stderr=subprocess.PIPEpara check_outputpode causar conflitos . Quando a segurança não é uma preocupação, você também pode executar comandos shell mais complexos, passando shell=Trueconforme descrito nas notas abaixo.
Se você precisar canalizar stderrou passar a entrada para o processo, check_outputnão estará à altura da tarefa. Veja os Popenexemplos abaixo nesse caso.
Aplicativos complexos e versões herdadas do Python (2.6 e abaixo): Popen
Se você precisar de profunda compatibilidade com versões anteriores ou se precisar de funcionalidades mais sofisticadas do que as check_outputfornecidas, precisará trabalhar diretamente com Popenobjetos, que encapsulam a API de baixo nível para subprocessos.
O Popenconstrutor aceita um único comando sem argumentos ou uma lista contendo um comando como seu primeiro item, seguido por qualquer número de argumentos, cada um como um item separado na lista. shlex.splitpode ajudar a analisar seqüências de caracteres em listas formatadas adequadamente. Popenos objetos também aceitam vários argumentos diferentes para gerenciamento de E / S de processo e configuração de baixo nível.
Enviar entrada e capturar saída communicateé quase sempre o método preferido. Como em:
output = subprocess.Popen(["mycmd", "myarg"],
stdout=subprocess.PIPE).communicate()[0]
Ou
>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
Se você definir stdin=PIPE, communicatetambém permitirá que você transmita dados para o processo via 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 resposta de Aaron Hall , o que indica que em alguns sistemas, você pode precisar de conjunto stdout, stderre stdintodos PIPE(ou DEVNULL) para chegar communicateao trabalho em tudo.
Em alguns casos raros, você pode precisar de captura de saída complexa em tempo real. A resposta da Vartec sugere um caminho a seguir, mas outros métodos que não communicatesejam propensos a conflitos se não forem usados com cuidado.
Como em todas as funções acima, quando a segurança não é uma preocupação, você pode executar comandos shell mais complexos passando shell=True.
Notas
1. Executando comandos do shell: o shell=Trueargumento
Normalmente, cada chamada para run, check_outputou o Popenconstrutor executa um único programa . Isso significa que não há tubos sofisticados no estilo bash. Se você deseja executar comandos complexos do shell, pode passar shell=True, que todas as três funções suportam.
No entanto, isso gera preocupações de segurança . Se estiver fazendo algo além de scripts leves, convém chamar cada processo separadamente e passar a saída de cada um como entrada para a próxima, via
run(cmd, [stdout=etc...], input=other_output)
Ou
Popen(cmd, [stdout=etc...]).communicate(other_output)
A tentação de conectar tubos diretamente é forte; resista. Caso contrário, você provavelmente verá impasses ou precisará fazer coisas hacky como essa .
2. Considerações Unicode
check_outputretorna uma string no Python 2, mas um bytesobjeto no Python 3. Vale a pena dedicar um momento para aprender sobre o unicode, se você ainda não o fez.