2008-08-24 8 views

Répondre

9

Si vous parlez de l'interpréteur python ou CMD.exe qui est le «parent» de votre script, alors non, ce n'est pas possible. Dans chaque système semblable à POSIX (maintenant vous avez Windows, semble-t-il, et qui pourrait avoir des bizarreries 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 Bu (lors de l'exécution dans une console) celles-ci sont dirigées vers la console, mais la redirection est possible en utilisant la notation de tuyau:

python script_a.py | python script_b.py 

Ceci lie le flux de sortie standard de l'écriture d'un au flux d'entrée standard du scénario B. L'erreur standard va toujours à la console dans cet exemple. Voir l'article sur standard streams sur Wikipedia.

Si vous parlez d'un processus enfant, vous pouvez le lancer à partir de Python comme si (stdin est également une option si vous voulez 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 module Python subprocess pour plus d'informations sur la gestion du processus. Pour la communication, les tubes process.stdin et process.stdout sont considérés comme des standards file objects.

Pour une utilisation avec des tuyaux, la lecture de l'entrée standard comme lassevk suggéré que vous feriez quelque chose comme ceci:

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

sys.stdin et sys.stdout sont des objets de fichier standard comme indiqué ci-dessus, défini dans le sys module. Vous pouvez également jeter un oeil au module pipes.

Lire des données avec readline() comme dans mon exemple est une façon assez naïve d'obtenir des données. Si la sortie n'est pas orientée ligne ou indéterministe, vous voulez probablement regarder dans polling qui malheureusement ne fonctionne pas dans Windows, mais je suis sûr qu'il existe une alternative là-bas.

+1

Notez que lors de l'appel Python à l'aide subprocess.Popen(), il est souvent utile de passer le drapeau « -u », qui désactive le tampon stdin/stdout/stderr. Python n'autoflush pas stdout lorsque l'enfant commence à lire stdin, si la sortie a été redirigée vers un canal, de sorte que vous pouvez bloquer définitivement la sortie de lecture qui est mise en mémoire tampon. J'ai rencontré ce problème en essayant d'envelopper/automatiser pdb. –

0

Dans quel contexte posez-vous cette question?

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

si oui, alors voici comment l'exécuter:

somescript.py | your-capture-program-here 

et lire la sortie, juste de lire l'entrée standard. Si, d'autre part, vous exécutez ce script ou cmd.exe ou similaire à partir de votre programme, et que vous voulez attendre que le script/programme soit terminé, et capturer toutes ses sorties, alors vous devez Regardez les appels de bibliothèque que vous utilisez pour démarrer ce programme externe, il y a probablement un moyen de lui demander de vous donner un moyen de lire la sortie et d'attendre la fin.

1

Vous voulez subprocess. Regardez spécifiquement Popen en 17.1.1 et communiquez en 17.1.2.

3

En fait, vous pouvez certainement, et c'est beau, moche, et fou en même temps!

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

Voici un exemple, l'enregistrer comme 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écutez ce programme, vous verrez que:

  • rien est allé à la sortie standard (où impression généralement des impressions à)
  • la première chaîne qui sont écrites sur stderr est celle qui commence par «Il
  • les deux lignes suivantes sont celles qui ont été recueillies dans l'objet StringIO

Remplacer sys.stdout/err comme ceci est une application de ce qu'on appelle monkeypatching. Les opinions peuvent varier, que ce soit «soutenu» ou non, et c'est définitivement un hack moche, mais il a sauvé mon bacon en essayant d'emballer des trucs externes une ou deux fois.

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

4

Je pense que je peux 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éteur Python à partir d'un script Python ?

La réponse est « oui », et personnellement j'aime ce qui suit soulevé des exemples dans le document PEP 343 -- The "with" Statement.

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 bel aspect de ce que peut être appliquée de manière sélective autour d'une partie seulement d'une exécution de script plutôt que toute son étendue, et reste en vigueur même lorsque des exceptions non gérées sont levées dans son contexte. Si vous ouvrez le fichier dans append mode 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 sûr, le pourrait aussi être au-dessus étendu pour rediriger également sys.stderr au même ou un autre fichier. Voir aussi cette answer à une question connexe.

Questions connexes