sous-processus popen.communiquer() vs stdin.write() et la sortie standard stdout.lire()
J'ai remarqué deux comportements différents avec deux approches qui devraient avoir le même résultat.
Le but d'exécuter un programme externe à l'aide de sous-processus module, envoyer des données et de lire les résultats.
Le programme externe est PLINK, la plate-forme est WindowsXP, une version de Python 3.3.
L'idée principale-
execution=["C:\\Pr..\\...\\plink.exe", "-l", username, "-pw", "***", IP]
a=subprocess.Popen(execution, bufsize=0, stdout=PIPE, stdin=PIPE, stderr=STDOUT, shell=False)
con=a.stdout.readline()
if (con.decode("utf-8").count("FATAL ERROR: Network error: Connection timed out")==0):
a.stdin.write(b"con rout 1\n")
print(a.stdout.readline().decode("utf-8"))
a.stdin.write(b"infodf\n")
print(a.stdout.readline().decode("utf-8"))
else:
print("ERROR")
a.kill()
So far So good.
Maintenant, je veux être capable de faire une boucle (après chaque écriture dans le sous processus de la stdin), qui attend jusqu'expressions du FOLKLORE de la sous-processus de la sortie standard (stdout), l'imprimer, puis un autre stdin commande, et ainsi de suite.
J'ai donc d'abord essayé ce que les discussions précédentes sur le même sujet rendement (en direct de la sortie du sous-processus de commande, lire les sous-processus stdout ligne par ligne, python, sous-processus: la lecture de la sortie de sous-processus) .
Et ça n'a pas fonctionné (il se bloque jamais) parce que le PLINK processus est encore en vie jusqu'à ce que je le tuer moi-même, donc il ne sert à rien d'attendre la sortie standard (stdout) de la sous-processus pour atteindre les expressions du FOLKLORE ou de faire une boucle tant que stdout est vrai, car il sera toujours vrai que j'ai de le tuer.
J'ai donc décidé de lire à partir de stdout deux fois à chaque fois que je suis en train d'écrire sur stdin (suffisant pour moi)-
execution=["C:\\Pr..\\...\\plink.exe", "-l", username, "-pw", "***", IP]
a=subprocess.Popen(execution, bufsize=0, stdout=PIPE, stdin=PIPE, stderr=STDOUT, shell=False)
con=a.stdout.readline()
if (con.decode("utf-8").count("FATAL ERROR: Network error: Connection timed out")==0):
a.stdin.write(b"con rout 1\n")
print(a.stdout.readline().decode("utf-8"))
print(a.stdout.readline().decode("utf-8")) //the extra line [1]
a.stdin.write(b"infodf\n")
print(a.stdout.readline().decode("utf-8"))
print(a.stdout.readline().decode("utf-8")) //the extra line [2]
else:
print("ERROR")
a.kill()
Mais le premier extra readline()
se bloque toujours, comme je le comprends, pour la même raison que j'ai mentionnés. Le premier extra readline()
attend toujours pour la sortie, parce que la seule sortie était déjà lire dans le premier readline()
, et parce que PLINK est vivant, la fonction juste de "s'asseoir" là et attend pour une nouvelle sortie ligne pour obtenir.
J'ai donc essayé ce code, en espérant la même accrocher parce que PLINK ne meurt jamais, jusqu'à ce que je le tuer,
execution=["C:\\Pr..\\...\\plink.exe", "-l", username, "-pw", "***", IP]
a=subprocess.Popen(execution, bufsize=0, stdout=PIPE, stdin=PIPE, stderr=STDOUT, shell=False)
con=a.stdout.readline()
if (con.decode("utf-8").count("FATAL ERROR: Network error: Connection timed out")==0):
a.stdin.write(b"con rout 1\n")
print(a.stdout.readline().decode("utf-8"))
a.stdin.write(b"infodf\n")
print(a.stdout.readline().decode("utf-8"))
print(a.communicate()[0].decode("utf-8")) //Popen.communicate() function
else:
print("ERROR")
a.kill()
J'ai essayé parce que, selon la documentation de communicate()
, la fonction d'attendre jusqu'à ce que le processus est terminé, et puis il a fini. Aussi, il lit à partir de la sortie standard jusqu'à EOF. (même que de l'écriture et de la lecture stdout et stdin)
Mais communicate()
finitions et n'accroche pas, au contraire de la précédente bloc de code.
Ce qui me manque ici? pourquoi lors de l'utilisation de communicate()
la PLINK se termine, mais lors de l'utilisation de readline()
il ne fonctionne pas?
OriginalL'auteur user2162550 | 2014-01-15
Vous devez vous connecter pour publier un commentaire.
Votre programme sans
communicate()
blocages parce que les deux processus sont en attente sur l'autre pour écrire quelque chose avant d'écrire quelque chose de plus eux-mêmes.communicate()
ne fait pas l'impasse dans votre exemple, car il ferme le flux, comme la commandea.stdin.close()
serait. Cela envoie un EOF à votre sous-processus, de le laisser savoir qu'il n'y est pas plus de commentaires à venir, de sorte qu'il peut fermer, provoquant la fermeture de sa sortie, de sortea.stdout.read()
finalement retourne EOF (chaîne vide).Il n'y a pas de signal spécial que votre processus principal recevrez de votre sous-processus pour vous laisser savoir qu'il est en fait écrit les résultats d'une commande, mais est prêt pour une autre commande.
Cela signifie que pour communiquer dans les deux sens avec un sous-processus pour tenter de, vous devez lire le nombre exact de lignes que le processus secondaire envoie. Comme vous l'avez vu, si vous essayez de lire trop de lignes, vous de blocage. Vous pourriez être en mesure de utilisez ce que vous savez, telles que la commande que vous l'avez envoyé, et à la sortie que vous avez vu jusqu'à présent, de déterminer exactement le nombre de lignes à lire.
OriginalL'auteur Dan Getz
Le truc, c'est que lors de l'utilisation de
subprocess.Popen
votre code continue à être lu avant même la fin du processus. Essayer d'ajouter.wait()
à votre Popen appel (voir la documentation),Cela permettra d'assurer que l'exécution des finitions avant de passer à autre chose.
OriginalL'auteur tchuncly
Vous pouvez utiliser des threads pour écrire et lire en même temps, surtout si la sortie ne doit être imprimé à l'utilisateur:
OriginalL'auteur Dan Getz