IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

process qui se lance quand ça lui chante [Python 2.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut process qui se lance quand ça lui chante
    Bonjour à tou(te)s,

    je m'amuse avec subprocess pour me perfectionner en python, et alors que je pensais avoir compris, je tombe sur un bec...

    J'ai écrit un petit script qui créé un process (qui n'est autre que le même script avec le paramètre "slave" en +) et essaie de communiquer avec lui via stdin/stdout.
    Et je constate que le process fils ne commence que quand le père a fini !
    Voici le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    # encoding:latin1
     
    import sys
    if sys.argv[-1] == 'slave' :
        #------------------------------ partie SLAVE --------------------------------------------
     
        """process slave : renvoie ce qu'il reçoit jusqu'à ce qu'il reçoive "stop_slave"."""
        print 'slave starts'
        while 1 :
            command = raw_input()
            print 'slave received (%s)'%command
            if command == 'stop_slave' : break # PPALC : le slave a été stoppé (Protocole Propriétaire A La C...)
        print 'slave_stopped'                  # PPALC : pour stopper le thread du master
     
    else:
        #------------------------------ partie MASTER --------------------------------------------
     
        import time,subprocess,threading
     
        class Process :
            '''Classe qui crée un process et permet de communiquer avec lui via send et receive'''
     
            def __init__(self,*command):
                '''La ligne de commande du process dans la liste command'''
                self.process  = subprocess.Popen( command,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,shell=False )
                self.thread   = threading.Thread( None,self._receive_loop )
                self.received = []
                self.lock     = threading.Lock()
                #self.thread.daemon = True # si je laisse ça, le thread meurt avant même que le slave ne soit lancé et j'ai encore moins d'affichage...
                self.thread.start()
                time.sleep( 1 ) # laisse le temps au process de se lancer (ou pas... :-()
     
            def _receive_loop (self):
                '''thread en attente sur le stdout du process et qui permet de rendre le receive non bloquant'''
                while 1 :
                    print 'thread is waiting'
                    s = self.process.stdout.readline().strip('\n\r')
                    print 'thread received "%s"'%s
                    if s == 'slave_stopped' : break # PPALC : thread du master stoppé par le slave
                    with self.lock :
                        self.received += [s]
                print 'thread ends'
     
            def send ( self,data ):
                '''envoie la string data au process slave'''
                self.process.stdin.write( data+'\n' )
     
            def receive ( self ):
                '''renvoie la liste des string reçues du process slave depuis le dernier appel'''
                with self.lock :
                    res = self.received
                    self.received = []
                    return res
     
        '''process master : crée le process 'slave', lui envoie 10 strings arbitraires et enfin "stop_slave".'''
        p = Process('python',sys.argv[0],'slave') # slave = master + paramètre 'slave'
        for i in xrange( 10 ) :
            time.sleep( 0.1 )
            print 'master send "command_%d"'%i
            p.send('command_%d'%i )
            for s in p.receive() :
                print 'master received "%s"'%s
        p.send('stop_slave') # PPALC : le master stoppe le slave
        print 'master ends'
    et la sortie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    thread is waiting
    master send "command_0"
    master send "command_1"
    master send "command_2"
    master send "command_3"
    master send "command_4"
    master send "command_5"
    master send "command_6"
    master send "command_7"
    master send "command_8"
    master send "command_9"
    master ends
    thread received "slave starts"
    thread is waiting
    thread received "slave received (command_0)"
    thread is waiting
    thread received "slave received (command_1)"
    thread is waiting
    thread received "slave received (command_2)"
    thread is waiting
    thread received "slave received (command_3)"
    thread is waiting
    thread received "slave received (command_4)"
    thread is waiting
    thread received "slave received (command_5)"
    thread is waiting
    thread received "slave received (command_6)"
    thread is waiting
    thread received "slave received (command_7)"
    thread is waiting
    thread received "slave received (command_8)"
    thread is waiting
    thread received "slave received (command_9)"
    thread is waiting
    thread received "slave received (stop_slave)"
    thread is waiting
    thread received "slave_stopped"
    thread ends
    Exception : cannot join current thread
    Comme on le voit, le process fils (slave) ne commence qu'après la fin du process père (master)...
    J'ai essayé de jouer avec des sleep pour laisser le temps au fils de se lancer, mais rien n'y fait (même avec 10 sec).

    Comment expliquer ce phénomène ?
    Qu'ai-je raté ?
    (ça fait déjà un moment que je triture mon code et arpente les fora, et je suis toujours à sec... )

    Question subsidiaire (pour ceux ou celles qui auraient déjà résolu ce problème) :
    Comment rendre plus propre la terminaison du fils (sans définir un protocole propriétaire à la c... avec base de string prédéfinie ("stop_slave" ici)).

    Pour info, je tourne sous Windows 7 64 bits... je n'ai pas essayé sous un autre OS.

    Merci d'avance pour votre temps et vos réponses

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Dans la méthode:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            def send ( self,data ):
                '''envoie la string data au process slave'''
                self.process.stdin.write( data+'\n' )
    ajoutez un self.process.stdin.flush() pour forcer l'écriture dans le PIPE.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut
    Merci... j'ai essayé, mais ça ne marche pas...
    D'ailleurs, on voit bien dans la sortie, que le process fils n'est même pas lancé quand le père commence à écrire.
    Donc je n'ai pas l'impression que forcer l'écriture dans le PIPE change grand chose...

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par Captain'Flam Voir le message
    Merci... j'ai essayé, mais ça ne marche pas...
    D'ailleurs, on voit bien dans la sortie, que le process fils n'est même pas lancé quand le père commence à écrire.
    Donc je n'ai pas l'impression que forcer l'écriture dans le PIPE change grand chose...
    yeap, il faut faire des flush côté "slave" aussi pour que les informations remontent.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut
    Mmm... j'ai bien peur que ne ça change pas grand chose :
    Si le process slave n'est pas lancé, les flush n'y feront rien.

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par Captain'Flam Voir le message
    Mmm... j'ai bien peur que ne ça change pas grand chose :
    Si le process slave n'est pas lancé, les flush n'y feront rien.
    et bien tant pis pour vous.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Citation Envoyé par Captain'Flam Voir le message
    Mmm... j'ai bien peur que ne ça change pas grand chose :
    Si le process slave n'est pas lancé, les flush n'y feront rien.
    Pourtant si, le slave est bien lancé; s'il n'affiche pas encore 'slave start', c'est à cause du buffering.
    Ajoute des sys.stdout.flush() dans la partie slave et tu verras...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Ma fonction qui ce lance quand j'actualise ma page
    Par Netyoko dans le forum Langage
    Réponses: 4
    Dernier message: 22/08/2013, 19h08
  2. Pour quand un IE qui comprends ce qu'on lui demande
    Par tortuegenie dans le forum Général Conception Web
    Réponses: 7
    Dernier message: 30/01/2008, 15h30
  3. [PopupMenu] comment savoir qui le lance?
    Par eponette dans le forum Composants VCL
    Réponses: 11
    Dernier message: 30/08/2005, 20h22
  4. Bootloader qui ne lance pas le Kernel
    Par Jb59 dans le forum Programmation d'OS
    Réponses: 2
    Dernier message: 01/08/2005, 22h29
  5. Gérer ce qui se lance avec linux
    Par Harry dans le forum Mandriva / Mageia
    Réponses: 7
    Dernier message: 26/07/2004, 16h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo