Obtenir la sortie d’un autre programme en entrée à la volée

J’ai deux programmes que j’utilise de cette façon:

$ c_program | python_program.py 

c_program imprime quelque chose en utilisant printf() et python_program.py lit à l’aide de sys.stdin.readline()

Je voudrais que le processus python_program.py produise les résultats de c_program lorsqu’il imprime, immédiatement, afin qu’il puisse imprimer sa propre sortie en cours. Malheureusement, python_program.py ne reçoit son entrée qu’après la fin de c_program.

Comment puis-je resoudre ceci?

Il suffit de définir stdout pour qu’il soit mis en ligne au début de votre programme C (avant d’effectuer toute sortie), comme ceci:

 #include  setvbuf(stdout, NULL, _IOLBF, 0); 

ou

 #include  setlinebuf(stdout); 

Soit on travaillera sous Linux, mais setvbuf fait partie de la norme C et fonctionnera donc sur plus de systèmes.

Par défaut, stdout sera mis en mémoire tampon pour un tube ou un fichier ou pour une ligne mise en mémoire tampon pour un terminal. Comme la sortie standard est un canal dans ce cas, la valeur par défaut sera mise en mémoire tampon. S’il est mis en mémoire tampon, le tampon sera vidé lorsqu’il est plein ou lorsque vous appelez fflush(stdout) . S’il est mis en ligne, il sera automatiquement vidé après chaque ligne.

Ce dont vous avez besoin, c’est que votre programme C appelle fflush (stdout) après chaque ligne. Par exemple, avec l’outil GNU grep, vous pouvez appeler l’option ‘–line-buffered’, ce qui provoque ce comportement. Voir fflush .

Si vous pouvez modifier votre programme C, vous avez déjà reçu votre réponse mais je pensais inclure une solution pour ceux qui ne peuvent / ne vont pas modifier le code.

expect a un exemple de script appelé unbuffer qui fera l’affaire.

Tous les shells Unix (que je connais) implémentent des pipelines de shell via autre chose qu’un pty (en général, ils utilisent des pipes Unix! -); par conséquent, la bibliothèque d’exécution C / C ++ dans cpp_program saura que sa sortie n’est pas un terminal, et donc qu’elle tamponnera la sortie (en morceaux de quelques Ko à la fois). À moins que vous n’écriviez votre propre shell (ou semiquasimaybeshelloid) qui implémente des pipelines via pyt, je pense qu’il n’y a aucun moyen de faire ce dont vous avez besoin en utilisant la notation de pipeline.

La chose “shelloid” en question pourrait être écrite en Python (ou en C, ou Tcl, ou …), en utilisant le module pty de la bibliothèque standard ou l’abstraction de niveau supérieur basé sur elle comme pexpect , et le fait que les deux programmes à connecter via un “pipeline basé sur pty” sont écrits en C ++ et Python est sans importance. L’idée clé est de tromper le programme à gauche du canal en lui faisant croire que sa sortie standard est un terminal (c’est-à-dire qu’un pty doit être à la base de l’astuce) pour tromper sa bibliothèque d’exécution en bufferisation. Une fois que vous avez écrit un shelloid, vous l’appellerez avec une syntaxe telle que:

$ shelloid ‘cpp_program | python_program.py ‘

Bien sûr, il serait plus facile de fournir une “solution ponctuelle” en écrivant python_program en sachant qu’il doit générer cpp_program tant que sous-processus ET lui faire croire que sa sortie standard est un terminal ( python_program utiliserait alors directement pexpect , pour Exemple). Mais si vous avez un million de ces situations où vous voulez vaincre la mise en mémoire tampon normale effectuée par la bibliothèque d’exécution C fournie par le système, ou dans de nombreux cas où vous souhaitez réutiliser des filtres existants, l’écriture de shelloid pourrait être préférable.

Vous voudrez peut-être essayer de flush le stream stdout dans le programme cpp.

ok ça peut paraître stupide mais ça pourrait marcher:

sortir votre pgm dans un fichier

 $ c_program >> ./out.log 

développer un programme python qui lit la commande tail

 import os tailoutput = os.popen("tail -n 0 -f ./out.log") try: while 1: line = tailoutput.readline() if len(line) == 0: break #do the rest of your things here print line except KeyboardInterrupt: print "Quitting \n"