90 votes

Pipe la sortie standard du sous-processus vers une variable

Je veux exécuter une commande en pythong, à l'aide de la sous-processus module, et de stocker le résultat dans une variable. Cependant, je ne veux pas la sortie de la commande à imprimer vers le terminal. Pour ce code:

def storels():
   a = subprocess.Popen("ls",shell=True)
storels()

Je reçois la liste des répertoires dans le terminal, au lieu de l'avoir stocké dans a. J'ai aussi essayé:

 def storels():
       subprocess.Popen("ls > tmp",shell=True)
       a = open("./tmp")
       [Rest of Code]
 storels()

Ce imprime également la sortie de ls de mon terminal. J'ai même essayé cette commande avec la date un peu os.méthode de système, depuis l'exécution d' ls > tmp dans le terminal n'est pas imprimer ls pour le terminal à tous, mais les stocke dans tmp. Cependant, la même chose arrive.

Edit:

J'obtiens l'erreur suivante après avoir suivi marcog les conseils, mais seulement lors de l'exécution de plus en plus complexes de commande. cdrecord --help. Python crache ceci:

Traceback (most recent call last):
  File "./install.py", line 52, in <module>
    burntrack2("hi")
  File "./install.py", line 46, in burntrack2
    a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE)
  File "/usr/lib/python2.6/subprocess.py", line 633, in __init__
    errread, errwrite)
  File "/usr/lib/python2.6/subprocess.py", line 1139, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

130voto

marcog Points 39356

Pour obtenir la sortie de l' ls, utilisez stdout=subprocess.PIPE.

>>> proc = subprocess.Popen('ls', stdout=subprocess.PIPE)
>>> output = proc.stdout.read()
>>> print output
bar
baz
foo

La commande cdrecord --help de sorties vers stderr, de sorte que vous devez tuyau qui indstead. Vous devriez également rompre la commande dans une liste de tokens comme je l'ai fait ci-dessous, ou l'alternative est de passer à l' shell=True argument, mais il déclenche une expansé coque qui peut être dangereuse si on ne contrôle pas le contenu de la chaîne de commande.

>>> proc = subprocess.Popen(['cdrecord', '--help'], stderr=subprocess.PIPE)
>>> output = proc.stderr.read()
>>> print output
Usage: wodim [options] track1...trackn
Options:
    -version    print version information and exit
    dev=target  SCSI target to use as CD/DVD-Recorder
    gracetime=# set the grace time before starting to write to #.
...

Si vous avez une commande qui affiche à la fois la sortie standard stdout et stderr et vous souhaitez les fusionner, vous pouvez le faire par la tuyauterie stderr vers stdout et ensuite de prendre la sortie standard stdout.

subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

Comme mentionné par Chris Morgan, vous devriez être en utilisant proc.communicate() au lieu de proc.read().

>>> proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> out, err = proc.communicate()
>>> print 'stdout:', out
stdout: 
>>> print 'stderr:', err
stderr:Usage: wodim [options] track1...trackn
Options:
    -version    print version information and exit
    dev=target  SCSI target to use as CD/DVD-Recorder
    gracetime=# set the grace time before starting to write to #.
...

31voto

amicitas Points 1925

Si vous utilisez python 2.7 ou plus tard, de la façon la plus simple de le faire est d'utiliser l' subprocess.check_output() commande. Voici un exemple:

output = subprocess.check_output('ls')

Aussi rediriger stderr, vous pouvez utiliser les éléments suivants:

output = subprocess.check_output('ls', stderr=subprocess.STDOUT)



Dans le cas où vous souhaitez passer des paramètres à la commande, vous pouvez utiliser une liste ou utilisez invoquer un shell et l'utilisation d'une chaîne unique.

output = subprocess.check_output(['ls', '-a'])
output = subprocess.check_output('ls -a', shell=True)

12voto

Chris Morgan Points 22285

Avec a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE) , vous devez utiliser une liste ou utiliser shell=True ;

L'un ou l'autre fonctionnera. Le premier est préférable.

 a = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE)

a = subprocess.Popen('cdrecord --help', shell=True, stdout=subprocess.PIPE)
 

De même, au lieu d'utiliser Popen.stdout.read / Popen.stderr.read , vous devez utiliser .communicate() (reportez-vous à la documentation du sous-processus pour connaître la raison de cette modification).

 proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X