2012-09-28 1 views
1

J'ai un script parent.py essayant de lire stdout à partir d'un sous-processus sub.py en Python.Lecture à partir de tampons vidés ou non vidés

Le parent parent.py:

#!/usr/bin/python 
import subprocess 
p = subprocess.Popen("sub.py", stdout=subprocess.PIPE) 
print p.stdout.read(1) 

Et le sous-processus, sub.py:

#!/usr/bin/python 
print raw_input("hello world!") 

j'attendre en cours d'exécution parent.py d'imprimer le 'h' de "Bonjour tout le monde!". En fait, ça pend. Je peux seulement obtenir mon comportement attendu en ajoutant -u à sub.py la ligne de she-bang. Cela me rend confus parce que le commutateur -u ne fait aucune différence lorsque sub.py est exécuté directement à partir d'un shell; le shell est en quelque sorte privé du flux de sortie non vidé, contrairement à parent.py.

Mon but est d'exécuter un programme C en tant que sous-processus, donc je ne serai pas en mesure de contrôler si oui ou non il vide stdout. Comment se fait-il qu'un shell ait un meilleur accès à la sortie standard d'un processus que Python exécutant la même chose à partir de subprocess.Popen? Est-ce que je vais être capable de lire un tel flux stdout à partir d'un programme C qui ne vide pas ses tampons?

EDIT:

Voici un exemple mis à jour en fonction du commentaire de korylprince ...

## capitalize.sh ## 
#!/bin/sh 

while [ 1 ]; do 
    read s 
    echo $s | tr '[:lower:]' '[:upper:]' 
done 

######################################## 

## parent.py ## 
#!/usr/bin/python 
from subprocess import Popen, PIPE 

# cmd = [ 'capitalize.sh' ] # This would work 
cmd = [ 'script', '-q', '-f', '-c', 'capitalize.sh', '/dev/null'] 

p = Popen(cmd, stdin=PIPE) 
p.stdin.write("some string\n") 
p.wait() 

Lors de l'exécution par script, je reçois l'impression constante de nouvelles lignes (et si cela était un python, sous-processus, il déclencherait un EOFerror).

Répondre

1

Une alternative est

p = subprocess.Popen(["python", "-u", "sub.py"], stdout=subprocess.PIPE) 

ou les suggestions here.

Mon expérience est que oui, vous serez capable de lire de la plupart des programmes C sans effort supplémentaire.

L'interpréteur Python prend des mesures supplémentaires pour mettre en tampon sa sortie, c'est pourquoi il a besoin du commutateur -u pour désactiver la mise en mémoire tampon de sortie. Votre programme C typique ne le fera pas.

Je n'ai pas rencontré de programme (C ou autre) autre que l'interpréteur Python que je pensais utiliser et non dans un sous-shell.

+1

J'ai eu affaire à ce problème avant. Tous les programmes C ne fonctionneront pas. Il y a une commande unix impressionnante appelée script qui va faire fonctionner les choses pour vous.Voir ma question qui l'utilise de manière similaire: http://stackoverflow.com/questions/11131825/main-python-process-is-stopped-using-subprocess-calls-in-socketserver – korylprince

+0

Cela ne marche pas avec mon 'c_prog'. Si je redirige stdout vers un fichier, puis l'interruption du clavier, le fichier sera vide. Mais si je le laisse se terminer naturellement, la sortie le rend au fichier .. Je suppose que c'est lié. – ajwood

+0

@korylprince: Lorsque j'exécute les sous-processus via 'script' en utilisant des PIPE pour std et stdout, le sous-processus semble échouer avec une erreur EOFError. – ajwood

0

La raison pour laquelle le shell peut lire la sortie immédiatement, indépendamment de "-u" est que le programme que vous lancez depuis le shell a sa sortie connectée à un TTY. Lorsque le stdout est connecté à un TTY, il n'est pas tamponné (parce que c'est au TTY de mettre en mémoire tampon). Lorsque vous lancez le sous-processus python à partir de python, vous connectez stdout à un canal, ce qui signifie que vous êtes à la merci du sous-processus pour vider sa sortie quand il le souhaite.

Si vous cherchez à faire des interactions complexes avec un sous-processus, regardez dans this tutorial.

Questions connexes