2010-04-25 5 views
4

Je dois exécuter un outil sur environ 300 répertoires. Chaque course prend environ 1 minute à 30 minutes ou même plus que cela. J'ai donc écrit un script python ayant une boucle pour exécuter l'outil sur tous les répertoires les uns après les autres.Erreur d'écriture: tuyau cassé

mon script python a le code quelque chose comme:

for directory in directories: 
    os.popen('runtool_exec ' + directory) 

Mais quand je lance le script python je reçois les messages d'erreur suivants à plusieurs reprises:

.. 
tail: write error: Broken pipe 
date: write error: Broken pipe 
.. 

Tout ce que je fais est de vous connecter sur un serveur distant utiliser ssh où l'outil, le script python et les répertoires de sujet sont conservés. Lorsque je cours individuellement l'outil à partir de l'invite de commande en utilisant la commande comme:

runtool_exec directory 

cela fonctionne très bien. L'erreur "broken pipe" arrive seulement quand je cours en utilisant le script python. Une idée, solution de contournement?

Répondre

9

Les erreurs que vous voyez sont dues au fait que vous utilisez os.popen() pour exécuter la commande, ce qui signifie qu'un tube est ouvert et connecté à la commande stdout. Chaque fois que la commande (ou tout ce qu'il exécute sans rediriger stdout) veut écrire à stdout, il va essayer d'écrire dans le tube. Mais vous ne gardez pas le tuyau autour, puisque vous n'attribuez pas le résultat de os.popen() n'importe où, donc il est nettoyé par Python, et fermé. Ainsi, les processus qui tentent d'y écrire rencontrent un tuyau cassé et produisent l'erreur que vous voyez. (os.popen() ne fait pas redirigent stderr à la conduite, de sorte que vous voyez toujours les erreurs.)

Un autre problème dans votre os.popen() appel est que vous ne cochez pas pour vous assurer directory ne contient pas de caractères spéciaux à votre coquille. Si le répertoire contient une citation, par exemple, ou un *, des choses étranges peuvent se produire. En utilisant os.popen() comme c'est très mauvais.

Vous devez utiliser subprocess.Popen() à la place, et explicitement dire ce que vous voulez faire avec la sortie du processus (à la fois stdout et stderr.) Vous passez subprocess.Popen() une liste d'arguments (y compris la chose que vous voulez commencer) au lieu d'un seul chaîne, et il évite la coque tout à fait - pas besoin de santé mentale - vérifier vos ficelles. Si vous voulez vraiment ignorer la sortie, vous le feriez avec quelque chose comme:

devnull = open(os.devnull, 'w') 
for directory in directories: 
    subprocess.Popen(['runtool_exec', directory], stdout=devnull) 

bien que je recommande fortement au moins faire quelques vérifications rudimentaires sur le résultat de subprocess.Popen pour voir si le processus n'a pas s'exécuter prématurément ou avec un code d'erreur.

+0

Merci beaucoup pour votre réponse. Cela marche. Mais comment puis-je déterminer quel processus s'est terminé avec succès et lequel a eu une erreur? – Fahim

+0

et aussi comment déterminer quels processus sont encore en cours d'exécution? Y a-t-il un moyen d'attendre que les sous-processus se terminent? – Fahim

+0

J'essaie actuellement ceci: log = open (logFile, 'a'); process = subprocess.Popen (args, stdout = log) processus.wait() si traitement.returnCode> = 0: \t \t \t \t \t \t \t \t \t print 'fait! \t else: \t print 'Erreur! Le processus s'est mal terminé ' Mais je vois qu'il n'attend pas que les processus se terminent, et le code de retour est toujours 99. aidez s'il vous plaît. – Fahim