Guardar o resultado do subprocesso.O Popen chama num texto

estou a tentar fazer uma chamada de sistema em Python e armazenar a saída para um texto que posso manipular no programa Python.

#!/usr/bin/python
import subprocess
p2 = subprocess.Popen("ntpq -p")
Tentei algumas coisas, incluindo algumas das sugestões aqui:

a obter o resultado do subprocessamento.chamada()

Mas sem sorte.

Author: Community, 2010-03-23

9 answers

Em Python 2.7 ou Python 3

Em vez de fazer um objecto Popen directamente, pode usar o subprocess.check_output() função para guardar o resultado de um comando num texto:

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

Em Python 2.4-2.6

Usa o método communicate.

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

out é o que tu queres.

Nota importante sobre as outras respostas

Repara como passei no comando. O exemplo de "ntpq -p" traz à tona outra questão. Uma vez que Popen não invoque a linha de comandos, você irá usar uma lista com o comando e as opções-["ntpq", "-p"].
 384
Author: Mike Graham, 2017-09-12 21:48:09

Isto funcionou para mim para redireccionar o stdout (o stderr pode ser tratado da mesma forma):

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

Se não funcionar para si, por favor especifique exactamente o problema que está a ter.

 36
Author: Eli Bendersky, 2010-03-23 19:12:58

Assumindo que pwd é apenas um exemplo, é assim que o podes fazer:

import subprocess

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

Ver a documentação do subprocesso para outro exemplo e mais informação.

 21
Author: Mark Byers, 2010-03-23 19:19:21

Subprocesso.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]

No construtor de Popen, se shell for True, você deve passar o comando como uma cadeia em vez de como uma sequência. Caso contrário, basta dividir o comando em uma lista:

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

Se necessitar de ler também o erro-padrão, na inicialização do Popen, poderá configurar o stderr para subprocessamento.PIPE ou para subprocesso.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()
 19
Author: Paolo Rovelli, 2013-04-28 19:14:19
Isto funciona perfeitamente para mim.
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 
 11
Author: Patrick Wolf, 2014-06-11 20:10:51

Para o Python 2.7+ A resposta idiomática é usar subprocess.check_output()

Você também deve notar o tratamento dos argumentos ao invocar um subprocesso, pois pode ser um pouco confuso....

Se args é apenas um comando sem args próprio( ou você tem shell=True Conjunto), pode ser uma cadeia de caracteres. Caso contrário, deve ser uma lista.

Por exemplo... para invocar o comando ls, Tudo bem:

from subprocess import check_call
check_call('ls')

Isto também é:

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

No entanto, se se quiser passar alguns args para o comando shell, você não pode fazer isso:

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

Em vez disso, você deve passá-lo como uma lista:

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

A shlex.split() a função às vezes pode ser útil para dividir uma string em sintaxe shell-like antes de criar um subprocesso... assim:

from subprocess import check_call
import shlex
check_call(shlex.split('ls -al'))
 10
Author: Corey Goldberg, 2016-03-08 02:38:33
Isto foi perfeito para mim. Você terá o código de retorno, stdout e stderr em um tuple.
from subprocess import Popen, PIPE

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

Por Exemplo:

result = console('ls -l')
print 'returncode: %s' % result[0]
print 'output: %s' % result[1]
print 'error: %s' % result[2]
 6
Author: gravmatt, 2015-11-05 10:38:21
 import os   
 list = os.popen('pwd').read()
Neste caso, só terá um elemento na lista.
 4
Author: Alex, 2010-03-23 19:14:41

Eu escrevi uma pequena função baseada nas outras respostas aqui:

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

Utilização:

changeset = pexec('hg','id','--id')
branch = pexec('hg','id','--branch')
revnum = pexec('hg','id','--num')
print('%s : %s (%s)' % (revnum, changeset, branch))
 4
Author: mpen, 2013-05-08 20:40:51