sous-processus.Popen.stdout lecture stdout en temps réel (encore une fois)
Encore une fois, la même question.
La raison en est, je ne peux pas le faire fonctionner après la lecture de ce qui suit:
- En temps réel de l'interception de la sortie standard d'un autre processus en Python
- L'interception de la sortie standard d'un processus secondaire alors qu'il est en cours d'exécution
- Comment puis-je obtenir en temps réel des informations à partir d'un sous-processus.Popen en python (2.5)
- la capture de la sortie standard stdout en temps réel à partir de sous-processus
Mon cas, c'est que j'ai une console application écrite en C, permet de prendre pour exemple ce code dans une boucle:
tmp = 0.0;
printf("\ninput>>");
scanf_s("%f",&tmp);
printf ("\ninput was: %f",tmp);
Il lit en permanence de certains et écrit sur la sortie.
Mon code python pour interagir avec lui est la suivante:
p=subprocess.Popen([path],stdout=subprocess.PIPE,stdin=subprocess.PIPE)
p.stdin.write('12345\n')
for line in p.stdout:
print(">>> " + str(line.rstrip()))
p.stdout.flush()
Jusqu'à présent chaque fois que je lis formulaire p.stdout
il attend jusqu'à ce que le processus est terminé et génère ensuite une chaîne vide. J'ai essayé beaucoup de choses, mais toujours le même résultat.
J'ai essayé Python 2.6 et 3.1, mais la version n'a pas d'importance - j'ai juste besoin pour le faire fonctionner quelque part.
connexes: Comment interagir correctement avec un processus à l'aide de sous-processus module
Je suis venu ici avec la même question, il a trouvé la réponse ici stackoverflow.com/q/375427/168034
OriginalL'auteur Halst | 2010-06-29
Vous devez vous connecter pour publier un commentaire.
Essayer de lire et d'écrire à partir de tubes à un sous-processus est complexe en raison de la valeur par défaut de mise en mémoire tampon en cours dans les deux directions. Il est extrêmement facile d'obtenir un blocage lorsque l'un ou l'autre processus (parent ou enfant) est la lecture à partir d'un tampon vide, de l'écriture dans un tampon complète ou de faire un blocage de lire sur un tampon qui est en attente de données avant que le système des bibliothèques de chasse.
Pour les plus modestes quantités de données de la
Popen.communicate()
méthode pourrait être suffisant. Cependant, pour les données qui dépasse sa mise en mémoire tampon, vous auriez probablement se faire l'impasse processus (similaire à ce que vous êtes déjà voir?)Vous voudrez peut-être regarder pour plus de détails sur l'utilisation de la
fcntl
module et de faire l'un ou l'autre (ou les deux) de votre descripteurs de fichier non bloquant. Dans ce cas, bien sûr, vous aurez pour envelopper toutes les lectures et/ou écrit de ces descripteurs de fichiers dans la gestion des exceptions pour gérer les "EWOULDBLOCK" des événements. (Je ne me souviens pas exactement Python exception levée pour ces).Une approche complètement différente pour vos parents à utiliser le
select
module etos.fork()
... et pour le processus de l'enfant àexecve()
le programme cible directement après la manipulation de n'importe quel fichier dup()ing. (En gros vous être re-mettre en œuvre les parties dePopen()
mais avec des parents différents descripteur de fichier (PIPE) de manutention.D'ailleurs, .communiquer, au moins dans Python 2.5 et 2.6 des bibliothèques standard, ne traitera que les propos de 64 ko de données à distance (sur Linux et FreeBSD). Ce nombre peut varier en fonction de divers facteurs (y compris éventuellement les options de compilation utilisées pour compiler votre interpréteur Python, ou de la version de la libc étant liés). Ce n'est PAS simplement limité par la mémoire disponible (en dépit de J. F. Sebastian l'affirmation du contraire), mais est limitée à une beaucoup plus petite valeur.
Queue
module, mais il ne fonctionne pas du tout.+1 pour la mention de la mise en mémoire tampon comme le principal coupable, voir aussi Pourquoi ne pas utiliser un tuyau (popen())? à partir de
pexpect
docs. Mais la réponse est trop pessimiste, c'est à dire,.communicate()
pourrait fonctionner pour toutes les données qui peuvent être stockées en mémoire (beaucoup plus que la pipe a la taille du buffer). Aussifcntl
(probablement) ne fonctionne pas sur Windows et il n'est pas nécessaire de toute façon..communicate()
fonctionne. Les versions antérieures avaient probablement un bug qui est corrigé maintenant.OriginalL'auteur Jim Dennis
Pousser la lecture de la pipe dans un thread séparé des signaux lors d'une partie de la sortie est disponible:
Comment puis-je lire tous les disponible les données de sous-processus.Popen.stdout (non bloquant)?
OriginalL'auteur ddotsenko
La
bufsize=256
argument empêche12345\n
d'être envoyé au processus enfant dans un morceau inférieure à 256 octets, comme elle le sera lorsque l'omissionbufsize
ou de l'insertionp.stdin.flush()
aprèsp.stdin.write()
. Le comportement par défaut est de ligne-mise en mémoire tampon.Dans les deux cas vous devriez voir au moins une ligne vide avant de blocage émis par le premier
printf(\n...)
dans votre exemple.OriginalL'auteur IBue
Votre exemple ne nécessite pas de "temps réel" de l'interaction. Les ouvrages suivants:
où
a.out
est votre exemple de programme C.En général, pour un dialogue basé sur l'interaction avec un sous-processus, vous pourriez utiliser
pexpect
module (ou de ses analogues sur Windows):OriginalL'auteur jfs
J'ai eu le même problème, et "proc.communiquer()" ne permet pas de le résoudre, car il attend pour le processus de résiliation.
Voici donc ce qui fonctionne pour moi, sur Windows avec Python 3.5.1 :
Je suppose que creationflags et les autres arguments ne sont pas obligatoires (mais je n'ai pas le temps de tester), alors ce serait la syntaxe minimale :
OriginalL'auteur 2diabolos.com