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 :

Une console Python dans un QTextEdit ? [QtGui]


Sujet :

PyQt Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut Une console Python dans un QTextEdit ?
    Bonjour,

    Dans un de mes programmes, j'aimerais installer une console Python interactive dans le QTextEdit d'une fenêtre PyQt4. Un peu comme la partie interactive de Idle.

    J'ai cherché avec le module "code", mais je ne vois pas comment "brancher" les entrées et les sorties de l'interpréteur sur le QTextEdit.

    Quelqu'un a-t-il une piste?

    Merci d'avance!

  2. #2
    Expert confirmé

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Salut,

    Dans Eric c'est implémenté avec QScintilla, je ne sais si l'exemple peut aider.

    Sous Linux, il est là : /us/lib/python3.3/site-packages/eric5/QScintilla/Shell.py

    Je suppose que ce doit être à peu près pareil pour eric4 ('site-packages' ou 'dist-packages' selon la version)

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

    En fait, il y a plusieurs difficultés.
    La première étant qu'il faut s/classer InteractiveConsole pour redéfinir les méthodes:
    • runcode: il s'agit de récupérer les sorties qui vont dans .stdout, .stderr dans un buffer,
    • raw_input: pour qu'il lise où on veut.


    C'est ce que fait le code ci dessous.
    InteractiveConsole doit être s/classé pour définir les .read, .write, .quit qui vont bien.

    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
    import sys
    import code
    import io
     
    class InteractiveConsole(code.InteractiveConsole):
     
        def runcode(self, code):
            '''redefined runcode to trap sys.stdout/stderr'''
            saved_fds = sys.stdout, sys.stderr
            sys.stderr = sys.stdout = sio =  io.StringIO()
            try:
                exec (code, self.locals)
            except SystemExit:
                self.quit()
            except:
                self.showtraceback()
            finally:
                data = sio.getvalue()
                sio.close()
                sys.stdout, sys.stderr = saved_fds
                self.write(data)
     
        def raw_input(self, prompt):
            try:
                line = self.read(prompt)
            except Exception as e:
                log.exception (e)
                raise SystemExit()
            else:
                return line
     
        def write(self, data):
            raise NotImplementedError("fatal: abstract method!!!")
        def read(self, prompt):
            raise NotImplementedError("fatal: abstract method!!!")
        def quit(self):
            raise NotImplementedError("fatal: abstract method!!!")
     
    def test_basics():
        '''Check InteractiveConsole hooks work as expected'''
        class Console(InteractiveConsole): 
            def write(self, data):
                print (data)
            def read(self, prompt):
                return input(prompt)
            def quit(self):
                sys.exit()
        console.interact()
     
    if __name__ == '__main__':
        test_basics()
    L'autre difficulté est de "pousser" l'exécution d'une instance d'InteractiveConsole dans un thread et de "coller" les .read, .write avec le GUI. Mais çà ne devrait pas vous poser de soucis particulier // et j'ai pas le temps de nettoyer mon code pour "sortir" ce qui a poussé "autour" mais qui ne sert à rien.

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

  4. #4
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Ça y est: j'ai réussi!

    Merci à tous les 2 pour les idées. Je suis parti du module "code" qui est fait pour ça, et j'ai fait l'adaptation à PyQt4: ça n'a rien de simple... J'ai dû d'ailleurs consulter une centaine de pages web, et je n'ai rien trouvé de concret sur le sujet.

    Les principes que j'ai utilisés dans le code ainsi que le code lui-même sont sur mon site: http://python.jpvweb.com/mesrecettes...console_python

    Je ne suis pas sûr que ce soit encore parfait: disons que c'est une version beta . En particulier, je n'ai pas réussi à arrêter l'exécution de l'interpréteur avec un ctrl-C à cause du thread: l'exception KeyboardInterrupt ne marche pas.

    Pour l'instant, ce programme répond à mon besoin initial, mais je reste à l'écoute de toute suggestion d'amélioration!

    Un exemple de ce que ça donne ci-dessous, l'objectif étant de pouvoir afficher la fenêtre dans n'importe quel programme PyQt, y compris traité par cx_freeze et s'exécutant sur un PC sans Python:


  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    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 738
    Par défaut
    Salut,
    Bravo pour le temps passé à écrire le code.
    Corrigez quand même cette partie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        def read(self, prompt):
            """lit la chaine à interpréter"""
            # envoi l'invite pour affichage
            self.write(prompt)
            # retourne la chaine dès qu'il y en a une de saisie
            while self.texte==None:
                pass
            texte = self.texte
            self.texte = None
            return texte
    Car grosso modo, tant que l'utilisateur n'aura pas tapé "<Return>", je ne vois pas trop comment cela pourrait faire autre chose que de bouffer le CPU pour rien.
    - W
    PS: Je n'ai pas encore eu le courage de coder cela ;-(
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour wiztricks,

    Je viens d'apporter 3 modifs:

    - pour tenir compte de ta remarque, j'ai remplacé dans la boucle le "pass" par "sleep(0.1)". Cela épargnera un peu le CPU. Je n'ai pas trouvé mieux que cette boucle d'attente jusqu'à ce qu'il y ait une instruction à exécuter. Il faudrait qu'on puisse mettre le thread en sommeil, et le réveiller par un simple message, mais je ne sais pas faire. Si tu as une meilleure idée que la boucle, n'hésite pas!

    - il a fallu que je mette un shake-hand pour l'affichage (entre interpy.write et visu.affiche), sinon, l'interpréteur envoyait les affichages trop vite, et ça plantait Python. Cela se fait avec un drapeau (okwrite), et j'ai simplement ajouté un verrou (mutexokwrite de type QtCore.QMutex) puisqu'il peut être modifié par le programme principal et par le thread.

    - la 3ème modif est intéressante puisqu'elle permet de fournir des listes d'instructions à exécuter dès le lancement de l'interpréteur. Cela permettra, par exemple, d'importer automatiquement des modules de fonctions supplémentaires adaptées au domaine traité: scientifique, financier, construction, etc... Cela fera une super calculatrice spécialisée (sans clavier pour l'instant).

    Des explications supplémentaires et le nouveau code sur mon site (http://python.jpvweb.com/mesrecettes...console_python).

    Il reste, à mon avis, à neutraliser les touches clavier qui ont une fonction dans le QTextEdit mais qui ne sont pas compatibles avec l'utilisation en console Python, ainsi qu'à trouver une solution à cette histoire de contrôle-C pour arrêter une exécution trop longue ou défaillante.

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

    Le protocole me semble affreusement compliqué. Mais je n'ai pas encore eu le temps de regarder tout çà.

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

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

Discussions similaires

  1. Comment ouvrir une console Python dans Eclipse
    Par ptissendier dans le forum Eclipse
    Réponses: 2
    Dernier message: 24/02/2014, 11h12
  2. Réponses: 5
    Dernier message: 19/01/2011, 13h47
  3. Insérer une fenêtre Python dans un canevas Tcl
    Par astro824 dans le forum Tkinter
    Réponses: 0
    Dernier message: 13/07/2010, 15h28
  4. Definition d'une classe python dans plusieurs fichiers
    Par wfargo dans le forum Général Python
    Réponses: 3
    Dernier message: 05/12/2006, 23h03
  5. Réponses: 3
    Dernier message: 26/06/2006, 13h48

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