Vous ne pouvez pas utiliser p.stdout comme ça ; si vous demandez "tout le stdout", il ne sera disponible qu'à la fin du processus (ou au moment du remplissage du tampon du tuyau, ce qui peut prendre beaucoup de temps).
Vous devez lire le stdout du processus ligne par ligne.
while True:
ln = p.stdout.readline()
if '' == ln:
break
m = re.search("Thread (?P<id>\d+)", ln);
if m:
# use m.group() to extract information
# e.g. m.group('id') will hold the 12345 from "Thread 12345"
Il serait également préférable que stdout puisse être mis en tampon de ligne (habituellement il est entièrement mis en tampon lorsque cela est possible), mais je pense que cela ne peut être fait qu'à partir du programme appelé.
Nous avons deux tampons à considérer ici. Le premier est le tampon de sortie du programme C. Il peut être inexistant (sortie non tamponnée), tamponné par ligne ou entièrement tamponné (1K, 4K ou 8K sont quelques tailles possibles).
Dans le programme, un "printf()" est appelé. La sortie est la suivante :
- sortie, si non tamponné
- dans le tampon ; et ensuite toutes les lignes terminées par une nouvelle ligne dans le tampon sont sorties, si la ligne est mise en tampon ;
- dans la mémoire tampon ; puis les premiers 4K sont sortis, si la mémoire tampon est entièrement remplie de 4K et que la mémoire tampon est plus remplie que 4K.
Maintenant la sortie entre dans le pipe de Python. Là encore, elle peut être entièrement mise en tampon (stdout) ou en ligne (readline). Ainsi, la sortie est envoyée :
- selon la logique du programme python, s'il y a une ligne complète terminée par une nouvelle ligne dans le pipeline et que nous utilisons readline
- dans le tampon, s'il y a moins de 4K dans le pipeline et que nous utilisons "for ln in stdout".
Dans ce dernier cas, le tampon sera envoyé en morceaux de 4K à la logique Python.
Imaginons maintenant un ligne mise en mémoire tampon Programme C produisant une ligne de 1K caractères par seconde vers un programme Python (si le programme C est entièrement mis en mémoire tampon, il n'y a pas grand chose à faire !)
En lisant stdout en cycle, nous verrions (à l'intérieur de la boucle for) :
- t = 0 ... rien
- t = 1 ... rien (le tampon est rempli à 50%)
- t = 2 ... rien (le tampon est rempli à 75%)
- t = 3 ... QUATRE lignes de sortie
- t = 4 ... rien ...
En lisant à travers readline on obtiendrait :
- t = 0 ... une ligne
- t = 1 ... une ligne
- t = 2 ... une ligne
- t = 3 ... une ligne
EXEMPLE
Ici, je lance "ping -c 3 -i 2 127.0.0.1" afin d'obtenir trois paquets vers localhost à deux secondes d'intervalle. Une exécution de ping prend environ six secondes. Je lis la sortie de ping, et j'imprime un horodatage. L'ensemble de la sortie de ping est suffisamment petit pour tenir dans le tampon complet de Python.
#!/usr/bin/python
import subprocess
from time import gmtime, strftime
p = subprocess.Popen(["ping", "-c", "3", "-i", "2", "127.0.0.1"],
stdout=subprocess.PIPE)
for ln in p.stdout:
print strftime("%H:%M:%S", gmtime()) + " received " + ln
# Now I start the same process again, reading the input the other way.
p = subprocess.Popen(["ping", "-c", "3", "-i", "2", "127.0.0.1"],
stdout=subprocess.PIPE)
while True:
ln = p.stdout.readline()
if '' == ln:
break
print strftime("%H:%M:%S", gmtime()) + " received " + ln
La sortie que je reçois sur ma boîte Linux est, comme prévu :
(nothing for the first six seconds)
15:40:10 received PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
15:40:10 received 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.037 ms
15:40:10 received 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.034 ms
15:40:10 received 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.031 ms
15:40:10 received
15:40:10 received --- 127.0.0.1 ping statistics ---
15:40:10 received 3 packets transmitted, 3 received, 0% packet loss, time 3998ms
15:40:10 received rtt min/avg/max/mdev = 0.031/0.034/0.037/0.002 ms
15:40:10 received PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
15:40:10 received 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.041 ms
15:40:12 received 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.039 ms
15:40:14 received 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.035 ms
15:40:14 received
15:40:14 received --- 127.0.0.1 ping statistics ---
15:40:14 received 3 packets transmitted, 3 received, 0% packet loss, time 3999ms
15:40:14 received rtt min/avg/max/mdev = 0.035/0.038/0.041/0.005 ms