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

PyQt Python Discussion :

Redirection de stdout en C vers Python


Sujet :

PyQt Python

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 66
    Par défaut Redirection de stdout en C vers Python
    Bonjour,

    Je débute en pyqt et je m'essaie actuellement sur une IHM assez basique.
    Je souhaiterais récupérer la sortie stdout renvoyé par un programme en C et l'afficher dans une fenêtre de message d'erreur en pyqt mais alors comment s'y prendre?

    Sachant que mon programme C s’exécute avec le module ctype et la fonction cdll de ce module.

    Merci pour votre aide,

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Salut
    J'ai un truc similaire mais en Tk.

    Le principe est d'avoir une View de type texte dans laquelle ajouter des lignes 'à la fin' (add_line). Optionnellement, vous ne gardez que N lignes et la 'chose' est "scrollable".

    Après pour la plomberie d'envoi à la View les add_line() emit par un autre thread...
    Inspirez vous du tutoriel que Tyrtamos a concocté.

    Au boulot
    - W
    PS: Et si ma soupe n'est pas bonne, ralez!!!
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 66
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut
    J'ai un truc similaire mais en Tk.

    Le principe est d'avoir une View de type texte dans laquelle ajouter des lignes 'à la fin' (add_line). Optionnellement, vous ne gardez que N lignes et la 'chose' est "scrollable".

    Après pour la plomberie d'envoi à la View les add_line() emit par un autre thread...
    Inspirez vous du tutoriel que Tyrtamos a concocté.

    Au boulot
    - W
    PS: Et si ma soupe n'est pas bonne, ralez!!!

    Salut,

    Donc si j'ai bien compris le seul moyen pour moi est de passer par un thread qui va récupérer les lignes stdout dans un buffer et les renvoyer ou je veux ?
    Bon effectivement au boulot ...

    Merci pour ton aide camarade,
    a +

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Citation Envoyé par makia42 Voir le message
    Donc si j'ai bien compris le seul moyen pour moi est de passer par un thread qui va récupérer les lignes stdout dans un buffer et les renvoyer ou je veux ?
    Le rôle du thread est d'éviter de bloquer la mainloop du GUI en attendant que la commande envoie des "lignes" à afficher via .add_line.
    Si vous pensez que ce sera toujours assez rapide, vous pouvez vous en passer.

    Le design proposé par le tuto est un peu trop Qt everywhere. Pas facile de tester les différents bouts indépendamment les uns des autres et de faire des collages "opportunistes".
    Dans votre contexte, un truc minimaliste pourrait être:
    - créer le lanceur de la commande avec en paramètre la fonction de "print" de ce qui a été récupéré de stdout,
    - créer le widget qui affiche les lignes ajoutées avec .addline,
    - connecter un bouton au lanceur,
    - remplacer la fonction "print"
    - wrap du lanceur dans un thread s'il faut être asynchrone,
    Mais il a le mérite d'exister et de montrer comment articuler les différents "bouts".
    - W
    En gros, la trame ressemblerait plutôt à çà:
    (avec une "activité" réduite à afficher quelques lignes).

    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
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *
    from threading import Thread as Worker
    import time
     
    class TextLogger(QFrame):
     
        def __init__(self, parent=None):
     
            super(TextLogger, self).__init__(parent)
            tw = self._textWidget = QTextEdit(parent=self)
            tw.setReadOnly(True)
            self.connect(self, SIGNAL("add_line(QString)"), tw.insertPlainText)
     
        def add_line(self, text):
            self.emit(SIGNAL("add_line(QString)"), text + '\n')
     
    def activity(count, add_line):
        for x in range(count):
            add_line('line-%d' % x)
            time.sleep(0.1)
     
    if __name__ == "__main__":
        import sys
     
        app = QApplication(sys.argv)
        widget = TextLogger()
        widget.show()
        m = Worker(target=activity, args=(5, widget.add_line))
        m.start()
        app.exec_()
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    Si le but n'est que l'affichage il n'est peut être pas besoin de passer par un thread.
    Tous les GUI proposent des méthodes, non bloquantes, permettant d'exécuter du code après un temps donné (after en tkinter, gobject.timeout_add en gtk, etc) ce qui permet de lancer le dit code après le mainloop. Cela doit aussi exister en PyQt (que je ne connais pas). Ou s'écrire (ne rigolez pas...) dans le style
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    self.m = QtCore.QTimer(self);
    self.connect(self.m, QtCore.SIGNAL('timeout()'), self.mafonction)
    self.m.start(1000)
    Je suppose que si nécessaire il est possible de rafraichir tout cela (QCoreApplication::processEvent())
    A prendre avec des pincettes makia42 car, comme dit, je ne connais pas PyQt.

    @

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    Si le but n'est que l'affichage il n'est peut être pas besoin de passer par un thread.
    Oui mais ce que tu proposes via QTimer et post d'events qui seront traités par la main loop revient à ajouter une activité asynchrone i.e. c'est une autre façon de construire un "thread" sans passer par l'API Thread.
    Elle est intéressante mais (je trouve que c'est) plus compliqué.
    - W
    PS: Il faudrait que je prenne le temps d'écrire Worker qui fasse çà.
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Sans doute mais comme cette concierge de mainloop n'est en fait qu'un thread qui regarde se qui se passe dans l'immeuble pourquoi rajouter une couche ?
    Cela deviens plus compliquer lorsque l'on utilise l'event manager pour gérer une poller_routine avec une visit_method non bloquante.
    Dans le cas présent je suppose que la lecture du stdout/écriture des lignes en continu est bloquante. Si l'interface ne sert qu'a cela quel est le problème. Autant lancer le code bloquant après création de l'interface.
    J'avoue que c'est sans doute 'barbare' mais s'il existe des QCoreApplication::processEvent() et autres .update() c'est que la synchro n'est pas parfaite avec les wrapper. Même si c'est pour se retrouver (dans certains cas) avec de l'asynchrone c'est au moins gérer au même niveau (comprendre le gestionnaire d'évènement).

    @+

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    Sans doute mais comme cette concierge de mainloop n'est en fait qu'un thread qui regarde se qui se passe dans l'immeuble pourquoi rajouter une couche ?
    Parce que cela permet de construire et tester indépendamment les deux. la fonction activity - dans le code que j'ai posté - ne connaît de "l'extérieur" que la méthode add_line qu'on lui a passé en paramètre.

    QCoreApplication::processEvent() et autres .update() c'est que la synchro n'est pas parfaite avec les wrapper.
    Je ne comprends pas la phrase: "la synchro n'est pas parfaite avec les wrapper".

    Ceci dit, il faudrait, dans ce cas, coller des "processEvent()" à l'intérieur de la fonction "activity" et espérer qu'on puisse "partitionner" le traitement fait pour appeler processEvent() assez souvent si l'on souhaite que l'IHM ne soit pas bloqué.
    note: difficile de construire et tester indépendamment dans ce cas.

    Le fait est que nous ne savons pas la durée de ce qui sera lancé par popen ni la quantité d'information qui sera retournée par l'exécution de la commande. On pourrait très bien avoir une fenêtre TextLogger modale et bloquer l'IHM en attendant que la commande se termine sans avoir besoin de rien du tout - même pas de processEvent.

    Quel design choisir pour que le passage d'une option à l'autre puisse être fait avec un minimum de ré-écriture de code et de tests?
    C'est l'idée qu'essaie d'illustrer mon exemple.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 66
    Par défaut
    Re,

    Je crois aussi que l'utilisation d'un thread n'est pas utile, étant donné que je souhaite afficher une fenêtre de dialogue du type QErrorMessage qui récupère la sortie sur stdout.
    Enfin je pense, voici un bout du code contenant la condition de test sur laquel je souhaite récupérer stdout, avec une erreur volontaire "err.showMessage(stdout)" ne fonctionnant pas mais pour vous expliquer ce que je souhaite faire :
    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
    	def flash_firmware(self):
    	    	import ctypes
    	   	libdfu = cdll.LoadLibrary("dfulib.so")
    		if libdfu.openscb_flash("self.fname") == 1 :
    			err = QtGui.QErrorMessage(self)
    			err.setModal(True)
    			err.showMessage(stdout)
     
    		else :
    			self.thread = pThread(self.fname)	
    			self.connect(self.thread, QtCore.SIGNAL('setProgress'), self.setProgress)
    			self.connect(self.thread, QtCore.SIGNAL('FlashingDone'), self.setProgressDone)
    			self.progress = QtGui.QProgressDialog("Flashing " + (os.path.split(unicode(self.fname.toUtf8()))[-1]), "Stop Flashing", 0, 100, None)
    			self.progress.setWindowModality(QtCore.Qt.WindowModal)
    			self.progress.show()
    			self.thread.start()
    En vous remerciant pour votre attention !

  10. #10
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 305
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 305
    Par défaut
    Bonjour,

    Un exemple copié tel quel:
    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
     
        def get_images(self, rep, bind):
            """Download files from current camera.
     
            """ 
            old_rep = os.getcwd()
            os.chdir(rep)
            reply = subprocess.Popen(["gphoto2", "--get-file", r], 
                                    universal_newlines=True,
                                    stdout=subprocess.PIPE)
     
            while 1
                text = reply.stdout.readline()[:-2]
                if type(text) != str or text == '' and reply.poll() != None: 
                    break
                elif type(text) == str:
                    bind.appendPlainText(text)
                    QtCore.QCoreApplication.processEvents()
    Ici, bind est une instance d'un QPlainTextEdit

  11. #11
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Salut,

    Citation Envoyé par makia42 Voir le message
    Je crois aussi que l'utilisation d'un thread n'est pas utile, étant donné que je souhaite afficher une fenêtre de dialogue du type QErrorMessage qui récupère la sortie sur stdout.
    Juste pour vous chambrer, pourquoi y-a-t-il des threads dans votre code si ce n'est pas utile?
    Et oui, pour tester qu'un fichier existe et afficher un pop-up d'erreur, pas besoin de thread et c'est heureux.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  12. #12
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    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 699
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Bonjour,

    Un exemple copié tel quel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        def get_images(self, rep, bind):
           ... 
           while 1
                text = reply.stdout.readline()[:-2]
                if type(text) != str or text == '' and reply.poll() != None: 
                    break
                elif type(text) == str:
                    bind.appendPlainText(text)
                    QtCore.QCoreApplication.processEvents()
    Ici, bind est une instance d'un QPlainTextEdit
    Si les lignes remontent lentement, çà bloquera mais c'est peut être ce qu'on souhaite. Il y a peut être du code "autour" qui justifie cela mais, vous auriez pu déclarer une fonction/class (myprint) qui encapsule les appels à:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
                    bind.appendPlainText(text)
                    QtCore.QCoreApplication.processEvents()
    Dans votre cas, vous ne rafraichissez l'affichage qu'après avoir posté de nouvelles lignes...
    Vous auriez pu faire une chose comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        def get_images(self, rep, myprint=print):
           ... 
           while 1
                text = reply.stdout.readline()[:-2]
                if type(text) != str or text == '' and reply.poll() != None: 
                    break
                elif type(text) == str:
                    myprint(text)
    ce qui permettrait de tester "hors" Qt.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Redirection stdin / stdout
    Par Neitsa dans le forum Linux
    Réponses: 3
    Dernier message: 17/02/2007, 15h57
  2. Redirection de apache sur :80 vers iis sur :81
    Par lecter dans le forum Apache
    Réponses: 2
    Dernier message: 26/04/2006, 09h27
  3. Redirection de stdout en C
    Par gege2061 dans le forum Linux
    Réponses: 4
    Dernier message: 06/03/2006, 15h49
  4. redirection javascript d'un frame vers l'ensemble de la page
    Par etarip dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 31/05/2005, 15h54

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