8
votes

Nettoyage popen Python

Je voulais utiliser un python équivalent pour avoir des commandes de shell dans Perl. Quelque chose comme la version Python de Open (tuyau, "Command |").

Je vais au module de sous-processus et essayez ceci: xxx

Ceci fonctionne pour lire la sortie De la même manière que je voudrais au Perl, mais cela ne se nettoie pas. Lorsque je sompre l'interprète, j'obtiens xxx

sensibilisé sur STDERR quelques millions de fois. Je suppose que j'avais naïvement espéré tout cela serait pris en charge pour moi, mais ce n'est pas vrai. Appeler terminer ou tuer sur P ne semble pas aider. Regardez la table de processus, je vois que cela tue le processus / bin / sh, mais laisse le gzip enfant en place pour se plaindre de la tuyau cassée.

Quelle est la bonne façon de faire cela?


1 commentaires

Soignez-vous l'interprète avant que votre sous-processus p a fini?


4 Réponses :


0
votes

Comment avez-vous exécuté ce processus?

La manière appropriée est d'utiliser P>

p.communicate()


2 commentaires

Cela se produit même si je ne communique jamais avec le processus. Il suffit de créer l'objet p et puis de la sortie de l'interprète provoque ce problème.


Oui, si je me souviens bien, Popen exécute la commande. Communiquer () Attend alors que le processus soit terminé, les tampons sont rincé, etc., etc. Voir également check_call () .



3
votes

Après avoir ouvert le tuyau, vous pouvez travailler avec la sortie de commande: p.stdout : xxx


0 commentaires

0
votes

Vous devez attendre code> pour le processus de finition:

import subprocess
p = subprocess.Popen("cat /mach_kernel", shell=True,
                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()


0 commentaires

10
votes

Le problème est que le tuyau est plein. La sous-traitement s'arrête, attendant que le tuyau soit vide, mais votre processus (l'interpréteur de python) se cessa, brisant son extrémité du tuyau (d'où le message d'erreur).

p.wait () Ne vous aidera pas:

AVERTISSEMENT Ceci ifraquet Si le processus enfant génère suffisamment de sortie sur un tuyau STDOUT ou STDERR de sorte qu'il bloque l'attente du tampon de tuyau d'exploitation pour accepter plus de données. Utilisez communiquer () pour éviter cela.

http://docs.python.org/library/subprocess. html # subprocess.popen.wait

p.communicate () ne vous aidera pas:

note La lecture des données est tamponnée en mémoire, alors n'utilisez pas cette méthode si la taille de données est grande ou illimitée.

http://docs.python.org/library/subprocess. html # subprocess.popen.communica

p.stdout.read (num_bytes) ne vous aidera pas:

AVERTISTATEUR UTILISATION COMMUNIQUE () plutôt que .STDIN.WRITE , .STDOUT.READ ou ou ou .sderr.read Pour éviter les blocages en raison de l'un des autres tampons de tuyau d'exploitation remplissant et de bloquer le processus d'enfant.

http://docs.python.org/library/subprocess. html # subprocess.popen.stdout

La morale de l'histoire est, pour une sortie importante, subprocess.pipe vous deviendra à certains échec si votre programme tente de lire les données (il me semble que vous devrait être capable de mettre p.stdout.read (octets) dans un tandis que p.returncode n'est aucun: boucle, mais l'avertissement ci-dessus suggère que cela pourrait une impasse). < / p>

Les documents suggèrent de remplacer un tuyau d'obus avec ceci: xxx

avis que p2 prend son entrée standard directement à partir de P1 . Ceci devrait éviter les blocages, mais compte tenu des avertissements contradictoires ci-dessus, qui sait

Quoi qu'il en soit, si cette dernière partie ne fonctionne pas pour vous ( devrait , cependant), vous pouvez essayer de créer un fichier temporaire, écrivez toutes les données du premier appel à cela, puis en utilisant le fichier temporaire en tant que saisie du processus suivant.


0 commentaires