Stockez la sortie du sous-processus.Popen appel dans une chaîne de caractères

j'essaie de faire un appel système en Python et de stocker la sortie sur une chaîne que je peux manipuler dans le programme Python.

#!/usr/bin/python
import subprocess
p2 = subprocess.Popen("ntpq -p")

j'ai essayé quelques choses, y compris certaines des suggestions ici:

extraire la sortie du sous-processus.call ()

mais sans succès.

229
demandé sur Community 2010-03-23 22:05:01

9 réponses

en Python 2.7 ou Python 3

au lieu de faire un objet Popen directement, Vous pouvez utiliser la subprocess.check_output() fonction pour stocker la sortie d'une commande dans une chaîne de caractères:

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

En Python 2.4-2.6

utiliser la méthode communicate .

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

out est ce que vous voulez.

Note importante à propos des autres réponses

notez comment j'ai passé la commande. L'exemple "ntpq -p" soulève une autre question. Puisque Popen n'invoque pas le shell, vous utiliserez une liste de la commande et des options - ["ntpq", "-p"] .

384
répondu Mike Graham 2017-09-12 21:48:09

cela a fonctionné pour moi pour rediriger stdout (stderr peut être manipulé de manière similaire):

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

si cela ne fonctionne pas pour vous, s'il vous plaît spécifier exactement le problème que vous avez.

36
répondu Eli Bendersky 2010-03-23 19:12:58

en supposant que pwd n'est qu'un exemple, voici comment vous pouvez le faire:

import subprocess

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

voir la documentation de sous-processus pour un autre exemple et plus d'informations.

21
répondu Mark Byers 2010-03-23 19:19:21

sous-processus.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]

dans le constructeur Popen, si shell est True , vous devez passer la commande comme une chaîne plutôt que comme une séquence. Sinon, il suffit de diviser la commande en une liste:

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

si vous avez besoin de lire aussi l'erreur standard, dans L'initialisation Popen, vous peuvent ensemble stderr à sous-processus.Tubes ou à la sous-procédure .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
répondu Paolo Rovelli 2013-04-28 19:14:19

cela fonctionne parfaitement pour moi:

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
répondu Patrick Wolf 2014-06-11 20:10:51

pour Python 2.7+ la réponse idiomatique est d'utiliser subprocess.check_output()

vous devriez également noter le traitement des arguments lors de l'invocation d'un sous-processus, car il peut être un peu confus....

si args n'est qu'une seule commande sans args (ou si vous avez shell=True ), il peut s'agir d'une chaîne. Autrement, elle doit être une liste.

par exemple... pour appeler la "151970920 de la commande", ce qui est bien:

from subprocess import check_call
check_call('ls')

ainsi est-il:

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

cependant, si vous souhaitez passer quelques arguments pour la commande shell, vous ne peut pas faites ceci:

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

au lieu de cela, vous devez le passer comme une liste:

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

la fonction shlex.split() peut parfois être utile pour séparer une chaîne de caractères en syntaxe shell avant la création d'un sous-processus... comme ceci:

from subprocess import check_call
import shlex
check_call(shlex.split('ls -al'))
10
répondu Corey Goldberg 2016-03-08 02:38:33

C'était parfait pour moi. Vous obtiendrez le code de retour, stdout et stderr dans un 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)

Par Exemple:

result = console('ls -l')
print 'returncode: %s' % result[0]
print 'output: %s' % result[1]
print 'error: %s' % result[2]
6
répondu gravmatt 2015-11-05 10:38:21
 import os   
 list = os.popen('pwd').read()

Dans ce cas, vous n'avez qu'un seul élément dans la liste.

4
répondu Alex 2010-03-23 19:14:41

j'ai écrit une petite fonction basée sur les autres réponses ici:

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

Utilisation:

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