Comment capturer la sortie de l'interpréteur Python et/ou de CMD.EXE à partir d'un script Python ?

StackOverflow https://stackoverflow.com/questions/24931

  •  09-06-2019
  •  | 
  •  

Question

  1. Est-il possible de capturer la sortie de l'interpréteur Python à partir d'un script Python ?
  2. Est-il possible de capturer la sortie de Windows CMD à partir d'un script Python ?

Si oui, vers quelle(s) bibliothèque(s) dois-je me tourner ?

Était-ce utile?

La solution

Si vous parlez de l'interpréteur Python ou de CMD.exe qui est le « parent » de votre script, alors non, ce n'est pas possible.Dans chaque système de type POSIX (vous utilisez maintenant Windows, semble-t-il, et cela pourrait avoir une bizarrerie que je ne connais pas, YMMV), chaque processus a trois flux, une entrée standard, une sortie standard et une erreur standard.Par défaut (lors de l'exécution dans une console), ceux-ci sont dirigés vers la console, mais la redirection est possible en utilisant la notation pipe :

python script_a.py | python script_b.py

Cela lie le flux de sortie standard du script a au flux d’entrée standard du script B.L'erreur standard est toujours transmise à la console dans cet exemple.Voir l'article sur flux standards sur Wikipédia.

Si vous parlez d'un processus enfant, vous pouvez le lancer depuis python comme ceci (stdin est également une option si vous souhaitez une communication bidirectionnelle) :

import subprocess
# Of course you can open things other than python here :)
process = subprocess.Popen(["python", "main.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
x = process.stderr.readline()
y = process.stdout.readline()
process.wait()

Voir le Python sous-processus module pour obtenir des informations sur la gestion du processus.Pour la communication, les tubes process.stdin et process.stdout sont considérés comme standard objets fichier.

À utiliser avec des tuyaux, lecture à partir de l'entrée standard comme lassevk je vous ai suggéré de faire quelque chose comme ceci:

import sys
x = sys.stderr.readline()
y = sys.stdin.readline()

sys.stdin et sys.stdout sont des objets fichier standard comme indiqué ci-dessus, définis dans le système module.Vous voudrez peut-être aussi jeter un oeil à tuyaux module.

Lire des données avec readline() comme dans mon exemple est cependant une manière assez naïve d'obtenir des données.Si la sortie n'est pas orientée ligne ou indéterministe, vous souhaiterez probablement examiner vote qui ne fonctionne malheureusement pas sous Windows, mais je suis sûr qu'il existe une alternative.

Autres conseils

Je pense pouvoir vous indiquer une bonne réponse pour la première partie de votre question.

1.Est-il possible de capturer la sortie de l'interprète Python à partir d'un script Python?

La réponse est "Oui", et personnellement, j'aime ce qui suit tiré des exemples du PEP 343 -- L'instruction "avec" document.

from contextlib import contextmanager
import sys

@contextmanager
def stdout_redirected(new_stdout):
    saved_stdout = sys.stdout
    sys.stdout = new_stdout
    try:
        yield None
    finally:
        sys.stdout.close()
        sys.stdout = saved_stdout

Et utilisé comme ceci :

with stdout_redirected(open("filename.txt", "w")):
    print "Hello world"

Un aspect intéressant est qu'il peut être appliqué de manière sélective sur une partie seulement de l'exécution d'un script, plutôt que sur la totalité de son étendue, et qu'il reste en vigueur même lorsque des exceptions non gérées sont déclenchées dans son contexte.Si vous rouvrez le fichier en mode ajout après sa première utilisation, vous pouvez accumuler les résultats dans un seul fichier :

with stdout_redirected(open("filename.txt", "w")):
    print "Hello world"

print "screen only output again"

with stdout_redirected(open("filename.txt", "a")):
    print "Hello world2"

Bien entendu, ce qui précède pourrait également être étendu pour rediriger également sys.stderr au même fichier ou à un autre fichier.Regarde aussi ceci répondre à une question connexe.

En fait, c'est tout à fait possible, et c'est beau, moche et fou à la fois !

Vous pouvez remplacer sys.stdout et sys.stderr par des objets StringIO qui collectent la sortie.

Voici un exemple, enregistrez-le sous evil.py :

import sys
import StringIO

s = StringIO.StringIO()

sys.stdout = s

print "hey, this isn't going to stdout at all!"
print "where is it ?"

sys.stderr.write('It actually went to a StringIO object, I will show you now:\n')
sys.stderr.write(s.getvalue())

Lorsque vous exécuterez ce programme, vous verrez que :

  • rien n'est allé sur la sortie standard (où l'impression s'imprime habituellement)
  • la première chaîne écrite dans stderr est celle qui commence par "It"
  • les deux lignes suivantes sont celles qui ont été collectées dans l'objet StringIO

Remplacer sys.stdout/err comme ceci est une application de ce qu'on appelle Monkeypatching.Les opinions peuvent varier, que cela soit « pris en charge » ou non, et c'est certainement un vilain hack, mais cela m'a sauvé la vie en essayant d'enrouler des éléments externes une ou deux fois.

Testé sous Linux, pas sous Windows, mais cela devrait tout aussi bien fonctionner.Faites-moi savoir si cela fonctionne sous Windows !

Tu veux sous-processus.Regardez spécifiquement Popen en 17.1.1 et communiquez en 17.1.2.

Dans quel contexte posez-vous la question ?

Essayez-vous de capturer la sortie d'un programme que vous démarrez sur la ligne de commande ?

si c'est le cas, voici comment l'exécuter :

somescript.py | your-capture-program-here

et pour lire la sortie, il suffit de lire à partir de l'entrée standard.

Si, d'un autre côté, vous exécutez ce script ou cmd.exe ou similaire à partir de votre programme et que vous souhaitez attendre que le script/programme soit terminé et capturer toute sa sortie, vous devez alors consulter la bibliothèque. appels que vous utilisez pour démarrer ce programme externe, il existe très probablement un moyen de lui demander de vous donner un moyen de lire la sortie et d'attendre la fin.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top