128 votes

Python : Comment obtenir stdout après avoir lancé os.system ?

Je veux obtenir le stdout dans une variable après avoir exécuté le os.system appeler.

Prenons cette ligne comme exemple :

batcmd="dir"
result = os.system(batcmd)

result contiendra le code d'erreur ( stderr 0 sous Windows ou 1 sous linux pour l'exemple ci-dessus).

Comment puis-je obtenir le stdout pour la commande ci-dessus sans utiliser la redirection dans la commande exécutée ?

159voto

Martijn Pieters Points 271458

Si tout ce dont vous avez besoin est le stdout puis jetez un coup d'œil à subprocess.check_output() :

import subprocess

batcmd="dir"
result = subprocess.check_output(batcmd, shell=True)

Parce que vous utilisiez os.system() vous devez définir shell=True pour obtenir le même comportement. Vous devez tenir compte de la problèmes de sécurité sur le passage d'arguments non fiables à votre shell.

Si vous devez capturer stderr également, il suffit d'ajouter stderr=subprocess.STDOUT à l'appel :

result = subprocess.check_output([batcmd], stderr=subprocess.STDOUT)

pour rediriger la sortie d'erreur vers le flux de sortie par défaut.

Si vous savez que la sortie est du texte, ajoutez text=True pour décoder la valeur des octets retournés avec l'encodage par défaut de la plate-forme ; utilisez encoding="..." à la place si ce codec n'est pas adapté aux données que vous recevez.

25voto

Patrick Points 495

Ces réponses n'ont pas fonctionné pour moi. J'ai dû utiliser les réponses suivantes :

import subprocess
p = subprocess.Popen(["pwd"], stdout=subprocess.PIPE)
out = p.stdout.read()
print out

Ou comme une fonction (l'utilisation de shell=True était nécessaire pour moi sur Python 2.6.7 et check_output n'a pas été ajouté avant la 2.7, ce qui le rend inutilisable ici) :

def system_call(command):
    p = subprocess.Popen([command], stdout=subprocess.PIPE, shell=True)
    return p.stdout.read()

18voto

Syed Wasim Points 181
import subprocess
string="echo Hello world"
result=subprocess.getoutput(string)
print("result::: ",result)

11voto

user3731538 Points 11

J'ai dû utiliser os.system, car subprocess me donnait une erreur de mémoire pour les tâches plus importantes. Référence pour ce problème aquí . Donc, pour obtenir la sortie de la commande os.system, j'ai utilisé cette solution de contournement :

import os

batcmd = 'dir'
result_code = os.system(batcmd + ' > output.txt')
if os.path.exists('output.txt'):
    fp = open('output.txt', "r")
    output = fp.read()
    fp.close()
    os.remove('output.txt')
    print(output)

8voto

LateNiteOwl Points 101

Je voudrais m'étendre sur la solution Windows. En utilisant IDLE avec Python 2.7.5, lorsque j'exécute ce code à partir du fichier Expts.py :

import subprocess
r = subprocess.check_output('cmd.exe dir',shell=False) 
print r

...dans le shell Python, je n'obtiens QUE la sortie correspondant à "cmd.exe" ; la partie "dir" est ignorée. CEPENDANT, lorsque j'ajoute un commutateur tel que /K ou /C ...

import subprocess
r = subprocess.check_output('cmd.exe /K dir',shell=False) 
print r

...puis dans le shell Python, j'obtiens tout ce que j'attends, y compris la liste des répertoires. Woohoo !

Maintenant, si j'essaie de faire ces mêmes choses dans la fenêtre de commande DOS Python, sans le commutateur, ou avec le commutateur /K, la fenêtre semble se bloquer parce qu'elle exécute un sous-processus cmd.exe et qu'elle attend d'autres entrées - tapez 'exit' puis appuyez sur [enter] pour sortir. Mais avec le commutateur /K, cela fonctionne parfaitement et vous ramène à l'invite python. Très bien alors.

Je suis allé un peu plus loin... Je pensais que c'était cool... Quand je fais plutôt cela dans Expts.py :

import subprocess
r = subprocess.call("cmd.exe dir",shell=False) 
print r

...une nouvelle fenêtre DOS s'ouvre et reste là, affichant uniquement les résultats de "cmd.exe" et non de "dir". Lorsque j'ajoute le commutateur /C, la fenêtre DOS s'ouvre et se ferme très rapidement avant que je puisse voir quoi que ce soit (comme prévu, car /C se termine une fois terminé). Lorsque j'ajoute à la place le commutateur /K, la fenêtre DOS s'ouvre et reste, ET j'obtiens tous les résultats que j'attends, y compris la liste des répertoires.

Si j'essaie la même chose (subprocess.call au lieu de subprocess.check_output) à partir d'une fenêtre de commande DOS Python, toute la sortie se fait dans la même fenêtre, il n'y a pas de fenêtres popup. Sans le commutateur, la partie "dir" est à nouveau ignorée, ET l'invite passe de l'invite python à l'invite DOS (puisqu'un sous-processus cmd.exe est exécuté en python ; tapez à nouveau 'exit' et vous reviendrez à l'invite python). L'ajout de l'option /K permet d'imprimer la liste des répertoires et de faire passer l'invite de python à DOS, puisque /K ne met pas fin au sous-processus. En remplaçant le commutateur par /C, on obtient tous les résultats attendus ET on revient à l'invite python puisque le sous-processus se termine conformément à /C.

Désolé pour cette longue réponse, mais je suis frustré sur ce forum par les nombreuses "réponses" laconiques qui, au mieux, ne fonctionnent pas (apparemment parce qu'elles n'ont pas été testées - comme la réponse d'Eduard F au-dessus de la mienne, où il manque le commutateur) ou pire, sont si laconiques qu'elles n'aident pas beaucoup (par exemple, "essayez le sous-processus au lieu de os.system" ... ouais, OK, et maintenant ? ?). En revanche, j'ai fourni des solutions que j'ai testées, et montré comment il existe des différences subtiles entre elles. Cela a pris beaucoup de temps mais... J'espère que cela vous aidera.

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