2017-09-16 2 views
2

Je cherche à m'interfacer avec une application de ligne de commande interactive utilisant Python 3.5. L'idée est que je commence le processus au début du script Python et le laisse ouvert. Dans une boucle, j'imprime un chemin de fichier, suivi d'un retour de ligne, à stdin, attendez environ un quart de seconde pendant le traitement et lisez stdout jusqu'à ce qu'il atteigne une nouvelle ligne.Sous-processus Python: Imprimer en stdin, lire stdout jusqu'à newline, répéter

Ceci est assez similaire à la fonctionnalité communicate de subprocess, mais j'attends un retour de ligne au lieu d'attendre la fin du processus. Quelqu'un est-il conscient d'une manière relativement simple de le faire? Editer: il serait préférable d'utiliser la bibliothèque standard pour cela, plutôt que des bibliothèques tierces telles que pexpect, si possible.

+4

Avez-vous regardé le module 'pexpect'? –

+0

@JonClements Je l'ai utilisé précédemment pour SSH. Je vais regarder pour cela cependant. Je vous remercie! –

+0

encore ... utiliser 'pexpect'. Il y a des complications gazillion qui est pourquoi l'utilisation de la bibliothèque standard ne peut pas être recommandée. –

Répondre

2

Vous pouvez utiliser subprocess.Popen pour cela.

Quelque chose comme ceci:

proc = subprocess.Popen(['my-command'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 

Maintenant proc.stdin et proc.stdout sont vos extrémités de tuyaux qui envoient des données au stdin subprocess et lu à partir du stdout subprocess. Puisque vous êtes uniquement intéressé par la lecture des lignes terminées par une nouvelle ligne, vous pouvez probablement contourner les problèmes causés par la mise en mémoire tampon. La mise en mémoire tampon est l'une des plus importantes lors de l'utilisation de sous-processus pour communiquer avec des processus interactifs. Habituellement, les entrées/sorties sont mises en mémoire tampon, ce qui signifie que si le sous-processus ne termine pas une ligne avec le saut de ligne, vous ne verrez peut-être aucune donnée sur proc.stdout, et vice versa lorsque vous écrivez à proc.stdin. ne se termine pas avec newline. Vous pouvez désactiver la mise en mémoire tampon, mais ce n'est pas si simple et pas indépendant de la plate-forme.

Un autre problème que vous pourriez avoir à résoudre est que vous ne pouvez pas déterminer si le sous-processus attend une entrée ou vous a envoyé une sortie sauf en écrivant et en lisant depuis les tuyaux. Vous devrez donc peut-être démarrer un deuxième thread pour pouvoir attendre la sortie sur proc.stdout et écrire simultanément sur proc.stdin sans tomber dans un interblocage car les deux processus bloquent sur les E/S de pipe (ou, si vous utilisez un Unix qui prend en charge select avec des handles de fichiers, utilisez select pour déterminer quels tuyaux sont prêts à recevoir ou prêts à être lus).

0

Cela ressemble à un travail pour une boucle d'événements. Le module subprocess commence à montrer sa déformation sous des tâches complexes.

Je l'ai fait avec Twisted, par le sous-classement suivant:

twisted.internet.endpoints.ProcessEndpoint 
twisted.protocols.basic.LineOnlyReceiver 

La plupart des documents pour Twisted utilise des sockets comme points d'extrémité, mais il est pas difficile d'adapter le code des processus.