Maison >développement back-end >Tutoriel Python >Pourquoi mon « sous-processus » Python se bloque-t-il lors de la lecture de la sortie d'un programme C utilisant « for line in iter(process.stdout.readline, \'\') » ?

Pourquoi mon « sous-processus » Python se bloque-t-il lors de la lecture de la sortie d'un programme C utilisant « for line in iter(process.stdout.readline, \'\') » ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-11-18 05:23:02735parcourir

Why Does My Python `subprocess` Hang When Reading Output from a C Program Using `for line in iter(process.stdout.readline, '')`?

Le sous-processus Python se bloque avec "for line in iter"

Dans ce scénario, le script Python est destiné à exécuter un programme C et à recevoir sa sortie. Cependant, le script se bloque à la ligne "for line in iter(process.stdout.readline, '')".

Le problème de mise en mémoire tampon

Le problème vient de un problème de mise en mémoire tampon. Dans les programmes C, stdout est généralement mis en mémoire tampon lorsque la sortie est redirigée. Cela signifie que la sortie est mise en mémoire tampon jusqu'à ce qu'une certaine quantité soit écrite ou qu'une nouvelle ligne soit rencontrée.

Dans le programme C, chaque itération de la boucle while imprime "2000" et reste en veille pendant une seconde. Puisqu'aucune nouvelle ligne n'est imprimée, la sortie est mise en mémoire tampon.

Pour la ligne dans le numéro Iter

En Python, subprocess.stdout.readline() lit la sortie standard de l'enfant processus et renvoie une ligne. La boucle "for line in iter()" parcourt les lignes renvoyées par readline().

Cependant, comme la sortie du programme C n'est pas vidée en raison de la mise en mémoire tampon, il n'y a aucune ligne à lire à ce moment-là. où le script Python entre dans la boucle. Par conséquent, le script attend indéfiniment sur cette ligne.

Solutions

Correction de la mise en mémoire tampon dans le programme C

  • setvbuf() : Le programme C peut utiliser setvbuf() pour forcer la mise en mémoire tampon des lignes pour sortie standard. Cela garantira que chaque ligne est vidée immédiatement après l'impression.
setvbuf(stdout, (char *) NULL, _IOLBF, 0);
  • Utilitaire stdbuf : L'utilitaire stdbuf peut être utilisé pour envelopper le programme C et modifier son mise en mémoire tampon comportement.
stdbuf -oL ./main

Pseudo-TTY

  • Module Pty : Le module pty peut être utilisé pour créer un pseudo-TTY qui fait croire au programme C qu'il s'exécute de manière interactive. Dans ce mode, la sortie sera mise en mémoire tampon de ligne par défaut.
import pty
master_fd, slave_fd = pty.openpty()
process = Popen("./main", stdin=slave_fd, stdout=slave_fd, stderr=STDOUT,
                bufsize=0, close_fds=True)
  • Bibliothèque pexpect : La bibliothèque pexpect fournit une interface de niveau supérieur pour travailler avec ptys.
import pexpect
child = pexpect.spawn("./main")
for line in child:
    print line

En appliquant l'une de ces solutions, le problème de mise en mémoire tampon sera résolu, permettant au script Python de lire le sortie du programme C comme prévu.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn