A resposta a esta pergunta depende da versão do Python que você está usando. A abordagem mais simples é usar a subprocess.check_output
função:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_output
executa 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 run
ou Popen
. Se você deseja executar comandos shell complexos, consulte a nota shell=True
no final desta resposta.
A check_output
funçã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 run
função é recomendada. Ele fornece uma API de alto nível muito geral para o subprocess
módulo. Para capturar a saída de um programa, passe o subprocess.PIPE
sinalizador para o stdout
argumento de palavra - chave. Em seguida, acesse o stdout
atributo do CompletedProcess
objeto 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 bytes
objeto; portanto, se você deseja uma sequência adequada, precisará decode
disso. 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 bytes
objeto para o input
argumento 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.stdout
junto 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=True
conforme 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 run
funçã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_output
funçã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 run
com check=True
e stdout=PIPE
, e retornar apenas o stdout
atributo.
Você pode transmitir stderr=subprocess.STDOUT
para garantir que as mensagens de erro sejam incluídas na saída retornada - mas, em algumas versões do Python, a passagem stderr=subprocess.PIPE
para check_output
pode causar conflitos . Quando a segurança não é uma preocupação, você também pode executar comandos shell mais complexos, passando shell=True
conforme descrito nas notas abaixo.
Se você precisar canalizar stderr
ou passar a entrada para o processo, check_output
não estará à altura da tarefa. Veja os Popen
exemplos 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_output
fornecidas, precisará trabalhar diretamente com Popen
objetos, que encapsulam a API de baixo nível para subprocessos.
O Popen
construtor 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.split
pode ajudar a analisar seqüências de caracteres em listas formatadas adequadamente. Popen
os 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
, communicate
també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
, stderr
e stdin
todos PIPE
(ou DEVNULL
) para chegar communicate
ao 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 communicate
sejam 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=True
argumento
Normalmente, cada chamada para run
, check_output
ou o Popen
construtor 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_output
retorna uma string no Python 2, mas um bytes
objeto no Python 3. Vale a pena dedicar um momento para aprender sobre o unicode, se você ainda não o fez.