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 :

Traitement de données d'un programme importé


Sujet :

Python

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 8
    Points : 9
    Points
    9
    Par défaut [Résolu] Traitement de données d'un programme importé
    Bonjour,
    Je cherche à faire un truc qui me parait simple sur le principe, mais vu que je ne trouve aucune indication sur le net malgré bien des recherches, je me demande si je cherche à faire quelque chose d'irréalisable (ce qui prouverait que mon raisonnement est faux) ou si c'est tellement simple que je suis passé à côté de quelque chose.

    J'ai un programme python (bavard.py) qui fonctionne correctement de façon indépendante (lancé directement). Il affiche des retours dans la console au fur et à mesure de sa longue progression. Un exemple pourrait être ce 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
     
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import os, sys
    import time
     
    def parle():
        print "Je fais ceci1"
        time.sleep(4)
        print "je fais cela2"
        time.sleep(10)
        print "Je fais ceci3"
        time.sleep(5)
        print "je fais cela4"
        time.sleep(3)
     
    if __name__ == '__main__':
        parle()
    Je cherche à pouvoir traiter les messages renvoyés par ce programme depuis un autre au fur et à mesure de leur apparition (pour afficher certains et pas d'autres en fonction de ce qui est voulu, pour les mettre dans une interface graphique, pour compter certaines opérations et ne renvoyer que ce résultat, ... Peu importe, l'important étant de les récupérer)

    J'arrive à créer mon programme, à importer bavard, à lancer bavard.parle() mais pas à traiter les messages au fur et à mesure

    J'ai essayé avec des threads, avec subprocess, les deux ensemble, mais à chaque fois, les messages arrivent tous d'un coup une fois le long traitement terminé. Et c'est pas le comportement souhaité.

    Je précise que je ne suis pas le mainteneur du programme bavard.py, qu'il est très long et spécifique, et qu'il n'est pas question de coller le code dans mon programme alors qu'il fonctionne bien seul et que ça deviendrait non maintenable à chaque mise à jour.

    J'ai bien compris qu'il me faut un thread principal qui va traiter les messages comme je le veux, un thread pour faire tourner bavard en arrière plan, et une queue pour la communication entre les deux.

    Comment recevoir et traiter les infos (que je vois sur la console) de bavard.parle() ?
    Comment envoyer ces messages dans la queue? J'ai même esssayé de rediriger stdout sans succès.

    Dans tous les cas, je n'ai pas réussi à faire un traitement simultané, les messages de bavard apparaissant d'un bloc à la fin du traitement. Alors que quand j'envoie manuellement (par code) des infos dans la queue, le traitement est effectué...

    J'apprécierais beaucoup un bout de code fonctionnel que je pourrais tester à loisir pour comprendre comment ça doit se passer, ou des indications pour arriver à faire fonctionner ce programme.
    Est ce qu'on peut arriver à faire ça avec python? Est ce que je demande un truc irréalisable? Est ce que mon raisonnement est à côté de la plaque et que je passe loin de la méthode?

    J'ai déjà plus de cheveux, mais je suis surpris à être le seul à avoir ce problème

  2. #2
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    Ben en fait, si tu ne peux/veux pas modifier bavard.py pour remplacer les print par autre chose, plutôt que de l'importer depuis ton propre programme, tu pourrais passer par le module subprocess qui te permet d'executer une commande shell et de créer des pipes pour pouvoir communiquer avec (dont un qui te permet de récuperer la sortie console d'un programme). Sa façon de fonctionner est très bien expliquer dans la doc de python.org

  3. #3
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Salut

    Voici une réponse à ton problème, si je l'ai bien compris.

    Dans la plupart des cas, le code ci-après suffira. Il crée un objet qui se chargera de rediriger le stdout et d'appeler un callback à chaque fois que quelque chose est écrit.

    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
    import sys
    import bavard
     
    class RelayOutput:
        def __init__(self, callback):
            self.__callback = callback
            self.__stdout = sys.stdout
     
        def start(self):
            sys.stdout = self
     
        def stop(self):
            sys.stdout = self.__stdout
     
        def write(self, text):
            # Retablir le stdout d'origine
            self.stop()
     
            # Process
            self.__callback(text)
     
            # Rediriger a nouveau le stdout
            self.start()
     
    def callback(text):
        # Un print fait 2 write: le texte, et le passage a la ligne
        text = text.strip()
     
        if text:
            print("I got a message: %s" % text)
     
    if __name__ == '__main__':
        ro = RelayOutput(callback)
     
        ro.start()
        bavard.parle()
        ro.stop()
    Pour les GUI, c'est le même principe en général, sauf qu'il faut faire appel aux threads. De plus, certaines librairies de GUI ont besoin d'un traitement spécifique pour les threads.
    Avec gtk par exemple, tu vas devoir utiliser gobject.idle_add pour pouvoir faire du travail asynchrone, sans quoi ton programme va se bloquer complètement.

    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
    65
    66
    67
    68
    69
    70
    71
    import sys
     
    import pygtk
    pygtk.require('2.0')
     
    import gtk, gobject
    from threading import Thread
     
    gtk.gdk.threads_init() # Important !
     
    import bavard
     
    class ThreadedRelayOutput:
        def __init__(self, callback):
            self.__callback = callback
            self.__stdout = sys.stdout
     
        def start(self):
            sys.stdout = self
     
        def stop(self):
            sys.stdout = self.__stdout
     
        def write(self, text):
            self.stop()
     
            # Ajouter un appel de methode a la queue de gtk
            gobject.idle_add(self.__callback, text)
     
            self.start()
     
    class MyNotifier(gtk.Window):
        def __init__(self):
            gtk.Window.__init__(self)
     
            self.__label = gtk.Label()
            btnStart = gtk.Button("Start")
            btnStart.connect("clicked", self.starter)
     
            box = gtk.VBox()
            box.pack_start(btnStart, False, False, 3)
            box.pack_start(self.__label, False, False, 3)
     
            self.add(box)
     
        def callback(self, text):
            text = text.strip()
     
            if text:
                self.__label.set_label(text)
     
        def starter(self, widget, data=None):
            t = Speaker(self.callback)
            t.start()
     
    class Speaker(Thread):
        def __init__(self, cb):
            Thread.__init__(self)
            self.__callback = cb
     
        def run(self):
            ro = ThreadedRelayOutput(self.__callback)
     
            ro.start()
            bavard.parle()
            ro.stop()
     
    if __name__ == '__main__':
        w = MyNotifier()
        w.show_all()
        gtk.main()

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 8
    Points : 9
    Points
    9
    Par défaut
    Merci Antoine_935 !
    C'est exactement ce que je voulais.
    J'ai enfin compris ce que je faisais de travers et comment l'adapter à mon programme. Ça fonctionne nickel.

    Rien de tel qu'un exemple simple pour que je comprenne.

    Merci encore.

  5. #5
    Membre éclairé
    Avatar de panda31
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Juin 2003
    Messages
    670
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Juin 2003
    Messages : 670
    Points : 848
    Points
    848
    Par défaut Redirection vers des fenêtres
    Bonjour,

    Ce fil semble correspondre à ce que je voudrais faire.
    Je cherche un moyen facile si possible de lancer des scripts/programmes/autres scripts python depuis un lanceur graphique et renvoyer leur sortie erreur et/ou standard vers des fenêtres prévues à cet effet dans mon IHM... Mais je ne trouve pas de doc ou alors je la comprends mal.
    Pourriez-vous me conseille svp ?

    Merci d'avance
    Michaël Mary
    Consultant PLM dans une société de conseil toulousaine
    Auditeur CNAM-IPST depuis septembre 2008
    "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."
    John F. Woods
    mon cv et mon domaine et mon blog
    Aucune question technique par MP, svp

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

Discussions similaires

  1. Programme de traitement des données manquantes
    Par stig_66 dans le forum Algorithmes et structures de données
    Réponses: 0
    Dernier message: 17/04/2013, 15h29
  2. [AC-2007] Importation Excel et traitement des données
    Par tyrael5 dans le forum VBA Access
    Réponses: 11
    Dernier message: 13/07/2012, 15h28
  3. [Formulaires] Traitement des données dans une autre page...
    Par sekiryou dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 04/03/2006, 09h08
  4. traitement des données avant envoie dans MySQL
    Par italiasky dans le forum SQL Procédural
    Réponses: 13
    Dernier message: 07/02/2006, 22h50
  5. Programmation pour traitement de données
    Par benbois dans le forum Langages de programmation
    Réponses: 16
    Dernier message: 19/10/2005, 17h01

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