L'exécution de la commande du shell et de la capture de la sortie
Je veux écrire une fonction qui va exécuter un shell de commande et de retourner sa sortie comme une chaîne de caractères, peu importe, est-ce une erreur ou un message de réussite. Je veux juste obtenir le même résultat que j'aurais obtenu avec la ligne de commande.
Ce qui serait un exemple de code qui permettrait de faire une telle chose?
Par exemple:
def run_command(cmd):
# ??????
print run_command('mysqladmin create test -uroot -pmysqladmin12')
# Should output something like:
# mysqladmin: CREATE DATABASE failed; error: 'Can't create database 'test'; database exists'
- connexes: stackoverflow.com/questions/2924310/...
Vous devez vous connecter pour publier un commentaire.
La réponse à cette question dépend de la version de Python que vous utilisez. L'approche la plus simple est d'utiliser le
sous-processus.check_output
fonction:check_output
exécute un programme simple qui ne prend que des arguments d'entrée.1 Elle renvoie le résultat exactement comme imprimé àstdout
. Si vous avez besoin d'écrire d'entrée àstdin
, passez à larun
ouPopen
sections. Si vous voulez exécuter complexe des commandes du shell, voir la note surshell=True
à la fin de cette réponse.La
check_output
fonctionne sur presque toutes les versions de Python encore en usage à l' (2.7+).2 Mais pour des versions plus récentes, il n'est plus l'approche recommandée.Moderne versions de Python (version 3.5 ou supérieure):
run
Si vous utilisez Python 3.5 ou plus, et n'ont pas besoin de rétro-compatibilité, le nouveau
exécuter
function est recommandé. Il offre une très général, l'API de haut niveau pour lasubprocess
module. Pour récupérer la sortie d'un programme, passer lesubprocess.PIPE
drapeau de lastdout
argument mot-clé. Alors accéder à l'stdout
attribut de retour de laCompletedProcess
objet:La valeur de retour est un
bytes
objet, donc si vous voulez une chaîne correcte, vous aurez besoin dedecode
il. En supposant que le processus appelé renvoie une codé en UTF-8 chaîne:Cela peut être compressé à un one-liner:
Si vous souhaitez passer des commentaires sur le processus de
stdin
, passer unebytes
objet de lainput
argument mot-clé:Vous pouvez capturer les erreurs en passant
stderr=subprocess.PIPE
(capture d'result.stderr
) oustderr=subprocess.STDOUT
(capture d'result.stdout
avec régulièrement des de sortie). Lorsque la sécurité n'est pas un problème, vous pouvez également exécuter plus complexe des commandes shell en passantshell=True
comme décrit dans les notes ci-dessous.Cela ajoute un peu de complexité, par rapport à l'ancienne façon de faire les choses. Mais je pense que ça vaut le résultat: maintenant, vous pouvez faire presque tout ce que vous devez faire avec le
run
seule fonction.Les anciennes versions de Python (2.7-3.4):
check_output
Si vous utilisez une ancienne version de Python, ou besoin d'un modeste rétro-compatibilité, vous pouvez probablement utiliser la
check_output
fonction que brièvement décrit ci-dessus. Il a été disponible depuis le Python 2.7.Il se prend les mêmes arguments que
Popen
(voir ci-dessous), et renvoie une chaîne contenant le programme de la sortie. Le début de cette réponse a une utilisation plus détaillés exemple. En Python 3.5 et supérieure,check_output
est équivalent à l'exécution derun
aveccheck=True
etstdout=PIPE
, et en retournant simplement lestdout
attribut.Vous pouvez passer
stderr=subprocess.STDOUT
pour s'assurer que les messages d'erreur sont inclus dans les résultats retournés -- mais dans certaines versions de Python en passantstderr=subprocess.PIPE
àcheck_output
peut causer les blocages. Lorsque la sécurité n'est pas un problème, vous pouvez également exécuter plus complexe des commandes shell en passantshell=True
comme décrit dans les notes ci-dessous.Si vous avez besoin d'un tuyau de
stderr
ou passer des commentaires sur le processus,check_output
ne soit pas à la tâche. Voir laPopen
exemples ci-dessous, dans ce cas.Applications complexes & anciennes versions de Python (2.6 et ci-dessous):
Popen
Si vous avez besoin profond d'une compatibilité ascendante, ou si vous avez besoin des fonctionnalités plus sophistiquées que
check_output
offre, vous aurez à travailler directement avec lesPopen
objets qui encapsulent les API de bas niveau pour les sous-processus.La
Popen
constructeur accepte une seule commande sans arguments, ou une liste contenant une commande par son premier élément, suivi d'un nombre quelconque d'arguments, chacun d'eux comme un élément distinct dans la liste.shlex.split
peut aider à analyser les chaînes dans le bon format de listes.Popen
objets aussi accepter une hôte de différents arguments de processus IO de gestion et de bas niveau de la configuration.Pour envoyer l'entrée et la sortie de capture,
communicate
est presque toujours la meilleure méthode. Comme dans:Ou
Si vous définissez
stdin=PIPE
,communicate
vous permet aussi de passer des données dans le processus viastdin
:Note Aaron Hall répondre, ce qui indique que sur certains systèmes, vous devrez peut-être définir
stdout
,stderr
, etstdin
tous àPIPE
(ouDEVNULL
) pour obtenircommunicate
de travailler à tous.Dans quelques rares cas, vous pouvez avoir besoin complexes en temps réel de la sortie de la capture. Vartec's réponse suggère une voie à suivre, mais d'autres méthodes que
communicate
sont sujettes à des blocages si pas utilisés avec soin.Comme avec toutes les fonctions ci-dessus, lorsque la sécurité n'est pas un problème, vous pouvez exécuter plus complexe des commandes shell en passant
shell=True
.Notes
1. L'exécution de commandes shell: le
shell=True
argumentNormalement, chaque appel à
run
,check_output
, ou lePopen
constructeur exécute une seul programme. Cela signifie pas de fantaisie, bash-style tuyaux. Si vous souhaitez exécuter le complexe des commandes du shell, vous pouvez passershell=True
, qui tous les trois fonctions de soutien.Cependant, cela soulève les problèmes de sécurité. Si vous faites quelque chose de plus que la lumière de script, vous pourriez être mieux appeler chaque processus séparément, et en passant à la sortie de chacun d'eux comme une entrée à l'autre, via
Ou
La tentation de connecter directement des tuyaux est forte d'y résister. Autrement, vous verrez probablement des blocages ou avez à faire hacky des choses comme cette.
2. Unicode considérations
check_output
retourne une chaîne de caractères en Python 2, mais unbytes
objet en Python 3. Il vaut la peine de prendre un moment pour apprendre sur unicode si vous ne l'avez pas déjà.check_output()
etcommunicate()
vous devez attendre jusqu'à ce que le processus est terminé, avecpoll()
vous êtes l'obtention de la sortie comme il vient. Dépend vraiment de ce que vous avez besoin.out
était de type<class 'bytes'>
pour moi. Afin d'obtenir le résultat sous la forme d'une chaîne, j'ai eu à décoder avant de lancer l'impression de la sorte:out.decode("utf-8")
bytes
sur toutes les versions de Python, à moins queuniversal_newlines=True
sur Python 3. Leprint
déclaration indique clairement qu'il est Python 2 code oùbytes = str
.ps aux | grep /usr/lib/evolution/evolution-calendar-factory-subprocess | grep webcal | grep -oE org.gnome.evolution.dataserver.Subprocess.Backend.Calendarx[0-9][0-9]+x[0-9]+
Quelle serait la bonne façon de traiter avec ce type de commande?shell=True
? Il soulève des problèmes de sécurité, mais il n'est pas difficile. La complexité supplémentaire est nécessaire, carcommands
a été unix seule et très limitée.cat output/* | wc -l
shell=True
? Il fonctionne pour moi. Vous n'avez pas besoinshlex.split
lorsque vous passezshell=True
.shlex.split
est pour les non-commandes du shell. Je pense que je vais prendre un peu parce que c'est pour brouiller les cartes.CompletedProcess
.) Popen retourne un objet représentant un processus qui peut encore être en cours d'exécution, et dispose de toutes les méthodes nécessaires à la manipulation d'un processus en cours d'exécution.subprocess.run('echo ":load /home/script.scala" | spark;')
, qui permet effectivement étincelle shell et exécuter le script scala, et je veux capturer l'ensemble de la sortie de la console vers le fichier de log, comment atteindre cet objectif, la commande échoue avec l'erreur fichier introuvable si je ne passe pas shell=True comme argumentcall
ne peut pas capturer la sortie, comme l'a demandé ici.check_output
est la façon la plus simple d'aller en Python 3.4, comme décrit ci-dessus.decode('unicode_escape')
pour le résultat.run()
nécessitecheck=True
afin de préserver le comportement decheck_output()
? (c'est à direCalledProcessError
lorsque les retours non nulle.) Je suppose que cela provoquerun()
attendre jusqu'à ce que le processus se termine. Je me demande ce qui est arrivé à l'impasse de la clause parce que c'est disparu dans les docs pourrun()
. Peut-être qu'il a été modifié et utilise maintenant une surabondance de la mémoire tampon.run
est une baisse-dans le remplacement pourcheck_output
. J'ai mentionné l'équivalence dans la plus moyen de discussion decheck_output
.input
comme dans cet exemple remplace un builtin.universal_newlines=True
qui vous permet de passer et de sortir des chaînes Unicode dans le système de codage par défaut. En 3,7 cela a été rebaptisé le plus sensibletext=True
.C'est plus facile, mais ne fonctionne que sous Unix (y compris Cygwin) et Python2.7.
Elle renvoie un tuple avec la (return_value, sortie).
Pour une solution qui fonctionne dans les deux Python2 et Python3, utilisez le
subprocess
module à la place:Quelque chose comme ça:
Note, que je suis rediriger stderr vers stdout, il pourrait ne pas être exactement ce que vous voulez, mais je veux les messages d'erreur également.
Cette fonction rendements ligne par ligne comme ils viennent (normalement, vous auriez à attendre pour les sous-processus pour terminer à obtenir la sortie dans son ensemble).
Pour votre cas, l'utilisation serait:
wait
etcall
fonctions.PIPE
valeur pourstdin
et la fermeture de ce dossier dès quePopen
retourne.retcode
est0
. Le chèque doit êtreif retcode is not None
. Vous devriez pas rendement des chaînes vides (même une ligne vide est au moins un symbole '\n'):if line: yield line
. Appelp.stdout.close()
à la fin.readlines()
(note de l's
) à la place.iter(p.stdout.readline, b'')
de runProcess() à la place de la boucle while.if retcode is not None: yield from p.stdout.readlines(); break
Vartec de l' réponse ne pas lire toutes les lignes, j'ai donc fait une version qui n':
Utilisation est la même que l'on a accepté la réponse:
return iter(p.stdout.readline, b'')
au lieu de la boucle whilep.stdout.readline()
peut retourner la non-vide précédemment mises en mémoire tampon de sortie, même si le processus de l'enfant ont quitté déjà (p.poll()
n'est pasNone
)..split()
.C'est un difficile mais super simple solution qui fonctionne dans de nombreuses situations:
Un fichier temporaire(ici est tmp) est créé avec la sortie de la commande et vous pouvez lire à partir de votre sortie désirée.
Note de vos commentaires:
Vous pouvez supprimer le fichier tmp dans le cas d'un travail à temps. Si vous avez besoin de faire cela plusieurs fois, il n'est pas nécessaire de supprimer la tmp.
mktemp
pour le faire fonctionner dans filetée situations, je supposeos.remove('tmp')
pour en faire un "fileless".En Python 3.5:
shell=True
. Voir aussi stackoverflow.com/questions/3172470/...J'ai eu le même problème, mais trouvé un moyen très simple de le faire:
Espère que cela aide
Remarque: Cette solution est Python3 spécifiques comme
subprocess.getoutput()
ne fonctionne pas en Python2getoutput
résout le cas le plus courant, et devrait être le premier résultatVous pouvez utiliser les commandes suivantes pour exécuter toutes les commandes shell. Je les ai utilisé sur ubuntu.
os.popen()
est obsolète dans la version 2.6 de Python, mais c'est pas, déprécié dans Python 3.x, puisque dans 3.x, il est mis en œuvre à l'aide desubprocess.Popen()
.Moderne Python solution (>= 3.1):
check_output()
est disponible depuis le Python 2.7.Votre Kilométrage Peut Varier, j'ai tenté @senderle du spin sur Vartec une solution de Windows sur Python 2.6.5, mais j'ai été faire des erreurs, et pas d'autres solutions travaillé. Mon erreur était:
WindowsError: [Error 6] The handle is invalid
.J'ai trouvé que je devais attribuer PIPE à chaque gérer pour obtenir un retour de la sortie que j'attendais la suite travaillé pour moi.
et de l'appeler comme ça, (
[0]
obtient le premier élément du tuple,stdout
):Après en avoir appris plus, je crois que j'ai besoin de ces tuyaux arguments parce que je suis en train de travailler sur un système personnalisé qui utilise différentes poignées, j'ai donc directement le contrôle de toutes les mst.
Pour arrêter la console de popups (avec Windows), faites ceci:
DEVNULL
à la place desubprocess.PIPE
si vous n'avez pas de lecture/écriture à partir d'un tuyau sinon, vous pouvez bloquer le processus de l'enfant.J'ai eu un peu différents de goût de le même problème avec les exigences suivantes:
mot-clé ci-dessus
J'ai combiné et tordu les réponses précédentes à venir avec les personnes suivantes:
Ce code sera exécuté le même que les réponses précédentes:
p.poll()
sans sommeil entre les deux appels, nous feraient perdre de cycles de PROCESSEUR par l'appel de cette fonction pour des millions de fois. Au lieu de cela, nous "accélérateur" notre boucle en racontant l'OS que nous n'avons pas besoin d'être dérangé pour les 1/10e de seconde, de sorte qu'il peut réaliser d'autres tâches. (Il est possible que p.poll() dort trop, de faire de notre sommeil déclaration redondant).Si vous avez besoin d'exécuter une commande shell sur plusieurs fichiers, cela a fait l'affaire pour moi.
Edit: Viens de voir Max Persson solution avec J. F. Sebastian de la suggestion. Allé de l'avant et intégrées.
Le fractionnement de la commande initiale pour la
subprocess
peut être difficile et fastidieux.Utilisation
shlex.split()
pour vous aider à vous en sortir.Exemple de commande
git log -n 5 --since "5 years ago" --until "2 year ago"
Le code
par exemple, execute ("ls -lah')
différencié trois/quatre retours et les plateformes OS:
fonction ci-dessous
Selon @senderle, si vous utilisez python3.6 comme moi:
Agira exactement comme vous exécutez la commande de bash
check=True, universal_newlines=True
. En d'autres termessubprocess.run()
déjà tout ce dont votre code ne.Si vous utilisez le
subprocess
module python, vous êtes en mesure de gérer le STDOUT, STDERR et code retour de la commande séparément. Vous pouvez voir un exemple pour la commande complète, appelant la mise en œuvre. Bien sûr, vous pouvez l'étendre avectry..except
si vous le souhaitez.Ci-dessous la fonction renvoie le STDOUT, STDERR et code de Retour de sorte que vous pouvez les traiter dans l'autre script.
subprocess.run()
. Ne pas réinventer la roue.La sortie peut être redirigée vers un fichier texte et puis le lire.