Forum Programmation.python Popen 2/3/4 utilisation

Posté par  .
Étiquettes : aucune
0
11
avr.
2005
Bonjour,
ma question fait suite a mon interrogation précédente : http://linuxfr.org/forums/29/7788.html(...)
Je suis mis a étudier popen. sa a effectivement l'air de correspondre a mes attentes. Cependant j'ai quelques difficultés. Je vient d'essayer de le mettre en place avec une commande très simple un ping :

i, o=os.popen4('ping 192.168.0.1')
print o.readline()


Bon j'ai essayé un peu tout, lire une ligne utiliser read(),popen2 et popen3 .... Bon mais cette commande ne fini jamais.
J'ai l'impression que le ping étant toujours entrain de rajouter des lignes au fichiers il est impossible pour le readline() soit de commencer la lecture soit de la finir car il ne trouve pas le caractère de fin.
avez vous une solution et/ou une explication?
  • # man ping

    Posté par  (site web personnel) . Évalué à 1.

    ping ne s'arrête jamais, si on ne le lui demande pas...
    option:
    -c count
    Stop after sending (and receiving) count ECHO_RESPONSE packets.
  • # ping -c

    Posté par  . Évalué à 2.

    Pour l'utilisation de popen tu peux regarder ce post : https://linuxfr.org/comments/514735.html#514735(...)

    Si ta commande ping ne se termine jamais, o.readline() va toujours te renvoyer quelque chose (la commande est terminée quand o.readline() retourne '' ou None).
    Pour résoudre ton problème, utilise l'option "-c 1" de ping pour arreter la commande après le 1er essai.
    • [^] # Re: ping -c

      Posté par  . Évalué à 1.

      je le savais qu'elle ne s'arrêter pas. C'est également le cas du véritable programme que je veux utiliser (j'avais mise le ping dans le forum a cause de cette propriété). Ce que je voudrais c justement pouvoir lire le résultat au fur et à mesure en utilisant un buffer ou quelque chose du genre. La grosse difficulté est que je ne peux pas retoucher le code de mon programme lancé en sub-process. donc je ne peux pas le fermer et le relancer.
      Dans l'optique ou cette manipulation est impossible, il y a t il une méthode pour au moins récupérer d'une quelconque manière l'ID du sub-process?
      • [^] # Re: ping -c

        Posté par  . Évalué à 3.

        Ping n'est pas un très bon exemple, car il ne réagit pas à la fermeture de stdout.

        Par exemple si tu fais :


        i, o = os.popen2('top -b')
        i.close()
        o.readline()
        # Tu fais les traitements nécessaires
        o.close()


        Là tu peux voir que la commande top c'est bien arrêtée. Ce n'est pas très clair comme principe, car ca dépend de la manière dont est gérée les sorties dans ton programme. A noter qu'un os.close(o.fileno()) peut mieux marcher dans certains cas (ne me demande pas pourquoi).

        Si tu veux agir plus finement, il te faut le pid : regarde alors du coté du module popen2 sous python2.3 ou subprocess sous python2.4. Avec le pid tu peux envoyer les signaux que tu veux.

        --
        Thomas
        • [^] # Sa avance

          Posté par  . Évalué à 0.

          Bon merci sa commence a mieux marcher.
          J'ai donc lancer ma commande avec popen2 et je récupère le file descriptor
          j'utilise après un pattern écouteur ( si mes souvenir en design pattern son juste)
          je crée un deuxième thread qui lit continuellement le fichier output de ma commande. En effet si je ne me trompe pas le "pseudo-fichier" n'a pas de caractère EOF par conséquent quand mon thread qui lit aura rattraper celui qui écrit il va attendre et ne quittera jamais sa fonction readline().
          donc pour le moment sa donne ceci :

          def run(self):

          input, output=os.popen2('cd '+self.path+ ' && '+ self.path+'/'+self.name) #cmd a ecouter
          input.close()
          return output

          def log(self, output):

          import thread
          tu = output, #création d'un tuple
          th = thread.start_new_thread(viewlog, tu ) #lancement du thread de lecture

          def viewlog( output): #thread qui lit
          lin =output.readline()
          while lin:
          print lin
          lin= output.readline()

          Mon problème est maintenant au niveau du thread de lecture qui doit écrire sur mon terminal . Il n'écrit pas de manière continue il écrit lorsque j'appuie sur une touche. j'aimerais bien arrêter l'écoute sur l'appui d'une touche. je ne comprend pas pourquoi mon thread de lecture écrit de cette façon. avez-vous une explication? Que pensez-vous de ma méthode?

          Je sais que je suis étreint de réaliser un truc un peu tordu. Mes explications sont sûrement confuse et je m'en excuse. dite vous que je veux réalisé un espèce de gestionnaire de démon capable de lancer/écouter/fermer un démon. *
          Merci tout le monde pour l'aide que vous m'avez déjà apporté.
          • [^] # Re: Ca avance

            Posté par  . Évalué à 2.

            A mon avis le problème ne vient pas de ton thread de lecture, mais du programme qui est lancé. Pour pouvoir lire le résultat en continu, il faut que ton programme fasse des "flush" assez régulièrement (ce que ton terminal fait plus ou moins tout seul). Sinon ton readline() ne peut pas retourner (il attend un flush ou un retour à la ligne).

            En clair, tout dépend de la commande que tu lances. Peut -être que lire par caractères (avec read(x)) fonctionnera mieux dans ton cas.

            --
            Thomas

            PS : ca serait encore plus plaisant de t'aider si tu faisais un petit effort d'orthographe/grammaire :)
            • [^] # Re: Ca avance

              Posté par  . Évalué à 0.


              PS : ca serait encore plus plaisant de t'aider si tu faisais un petit effort d'orthographe/grammaire :)


              je suis désolais si je fait encore des erreurs sache que je suis dyslexique et que ne pas faire de faute et extrêmement dur pour moi. Je passe un correcteur d'orthographe sur chacun de mes messages. Il s'agit un correcteur en ligne qui vaut ce qui vaut c'est à dire pas grand chose. Je n'ai pas trouver de correcteur de grammaire en ligne mais si jamais quelqu'un en connais ça m'intéresse.

              Sinon j'avais penser à la lecture caractère par caractère sa ne changer pas le problème. C'est pour sa j'utilise un thread pour la lecture c pour me permettre au niveau du thread supérieur de le tuer a la fin . Quand je travaillais sans ce thread je réussisse à lire la totalité et je resté bloquer a la fin . Je me suis dit que si je le mettais dans un thread je pourrai contrôler sont activité et l'arrêter a la fin.
              Mais en fessant cela j'ai l'impression que le thread n'a pas la main pour écrire sur le terminal et qu'il l'obtient un cour instant quand j'appuie sur une touche

              Je me demande si le fait que le thread qui lit et le thread qui écoute peuvent écrire dans le même terminal ne pose pas problème.
              • [^] # Re: Ca avance

                Posté par  . Évalué à 2.

                [détails vie privée]

                OK excuse moi on voit trop souvent des personnes ici qui ne font certainement pas l'effort que tu fais.

                Mais en fessant cela j'ai l'impression que le thread n'a pas la main
                pour écrire sur le terminal et qu'il l'obtient un cour instant quand
                j'appuie sur une touche
                Je me demande si le fait que le thread qui lit et le thread qui écoute
                peuvent écrire dans le même terminal ne pose pas problème.


                C'est possible la gestion des threads est toujours sensible, mais en gros ca devrait fonctionner.
                J'ai fait un petit exemple qui fonctionne chez moi (en m'inspirant de ton code):


                import os
                import thread
                import time

                def run(cmd):
                input, output= os.popen2(cmd)
                input.close()
                return output

                def log(output):
                th = thread.start_new_thread(viewlog, (output,))

                def viewlog(output):
                lin = output.readline()
                while lin:
                print lin
                lin = output.readline()

                if __name__ == "__main__":
                o = run("top -b")
                log(o)
                o = run("ping google.fr")
                log(o)
                while 1:
                time.sleep(1)
                print "wake"


                Après les commande que je lance (ping et top) ne sont peut-être pas un bon exemple, mais ca montre que tu peux arriver à sortir des données depuis différents threads.

                Si ton objectif est vraiment un contrôle de daemons, utiliser popen n'est pas le bon choix (il faut mieux utiliser un execv/fork et jouer avec les pids et les signaux). Si tu veux t'inspirer, il y a le module zdaemon de Zope qui fait quelque chose dans ce goût (browse, browse... ah : http://cvs.zope.org/Packages3/zdaemon/Attic/zdaemon.py(...) ).

                Bon courage en tout cas.

                --
                Thomas
                • [^] # Re: Ca avance

                  Posté par  . Évalué à 0.

                  Ok merci beaucoup j'ai rajouté une petit gestion d'exception et je peu quitter et revenir dans le log d'un de mes daemons sans problème.
                  Je vais regarder au niveau de execv/fork je doit avouer que je connais pas trop ce genre manipulation avec les signaux et sa me fait un peu peur (bon mais comme je suis courageux...).
                  Sinon une dernière question: il est possible d'arrêter un programme lancer par le popen2 ?

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.