Warning: Undefined array key "DOKU_PREFS" in /home/clients/a4e6fc1ce1761b72982b805de0f418c4/web/python/mesrecettespython/inc/common.php on line 2082
pyqt4_console_python [Les recettes Python de Tyrtamos]

Outils pour utilisateurs

Outils du site


pyqt4_console_python

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
Prochaine révision Les deux révisions suivantes
pyqt4_console_python [2013/01/28 06:18]
tyrtamos
pyqt4_console_python [2013/01/28 15:56]
tyrtamos
Ligne 2: Ligne 2:
  
 [Python v2.7.3, PyQt4 v4.9.5, Qt4 v4.8.3] [Python v2.7.3, PyQt4 v4.9.5, Qt4 v4.8.3]
 +
 +[modification le 28/1/2013 16h]
  
 ===== Objectif ===== ===== Objectif =====
Ligne 35: Ligne 37:
  
 L'idée initiale de ce code m'a été soufflée sur un forum ([[http://www.developpez.net/forums/d1301688/autres-langages/python-zope/gui/pyside-pyqt/console-python-qtextedit/]]): merci à wiztricks!  L'idée initiale de ce code m'a été soufflée sur un forum ([[http://www.developpez.net/forums/d1301688/autres-langages/python-zope/gui/pyside-pyqt/console-python-qtextedit/]]): merci à wiztricks! 
 +
 +Quelques modifications ont été faites depuis la toute 1ère publication (ce matin!). La plus importante est que l'on peut désormais fournir, dès le lancement, du code Python pour que l'interpréteur l'exécute au départ. 
 +
 +On peut ainsi:
 +
 +  * fournir une chaine de caractères: elle devra être le nom d'un fichier Python existant avec son chemin. Le fichier sera lu et ses lignes exécutées une par une.
 +
 +  * fournir une liste (ou un tuple) d'instructions Python: ces instructions seront exécutées une par une.
 +
 +Dans les 2 cas, les instructions seront exécutées comme si l'utilisateur les avaient tapées lui-même. 
 +
 +si l'argument transmis est une chaine mais que le fichier n'existe pas, ou est n'importe quoi d'autre qu'une liste ou un tuple, l'interpréteur n'en tiendra pas compte.   
 +
 +Voir les exemples fournis à la fin du code ci-dessous.
 +
 +Cette fonctionnalité va bien avec l'objectif de départ: quelque soit le domaine dans lequel on est (scientifique, financier, construction, etc...), on peut initialiser automatiquement la console avec des modules de fonctions adaptées, fonctions qu'on pourra utiliser dans la console comme avec une calculatrice spécialisée!
 +
  
 Voilà le code. Voilà le code.
Ligne 49: Ligne 68:
 import code import code
 import StringIO import StringIO
 +from time import sleep
  
 from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
 +
 +#############################################################################
 +# variables globales pour gérer les données communes avec le thread
 +
 +mutexokwrite = QtCore.QMutex()
 +okwrite = False
  
 ############################################################################# #############################################################################
Ligne 112: Ligne 138:
     def write(self, data):     def write(self, data):
         """affiche data en envoyant un message à la fenêtre"""         """affiche data en envoyant un message à la fenêtre"""
 +        global okwrite, mutexokwrite # drapeau pour le shake-hand d'affichage
 +        
         # pour être sûr que data est en unicode         # pour être sûr que data est en unicode
         if not isinstance(data, unicode):          if not isinstance(data, unicode): 
Ligne 120: Ligne 148:
         if data!=u"":         if data!=u"":
             # envoie la réponse sous forme de message (avec shake-hand)             # envoie la réponse sous forme de message (avec shake-hand)
-            self.affichageok = False+            mutexokwrite.lock() 
 +            okwrite = False 
 +            mutexokwrite.unlock()
             self.emit(QtCore.SIGNAL("pourafficher(PyQt_PyObject)"), data)              self.emit(QtCore.SIGNAL("pourafficher(PyQt_PyObject)"), data) 
-            while not self.affichageok:+            while not okwrite:
                 pass                 pass
                  
     #========================================================================     #========================================================================
     def textedispo(self, texte):     def textedispo(self, texte):
-        """exécuté à chaque message "pourlire" accompagné du texte """+        """exécuté à chaque message reçu "pourlire" accompagné du texte """
         self.texte = texte         self.texte = texte
          
Ligne 133: Ligne 163:
     def read(self, prompt):     def read(self, prompt):
         """lit la chaine à interpréter"""         """lit la chaine à interpréter"""
 +        
         # envoi l'invite pour affichage         # envoi l'invite pour affichage
         self.write(prompt)         self.write(prompt)
 +
         # retourne la chaine dès qu'il y en a une de saisie         # retourne la chaine dès qu'il y en a une de saisie
         while self.texte==None:         while self.texte==None:
-            pass+            sleep(0.1)
         texte = self.texte         texte = self.texte
         self.texte = None         self.texte = None
Ligne 151: Ligne 183:
 class Visu(QtGui.QTextEdit): class Visu(QtGui.QTextEdit):
          
-    def __init__(self, parent=None):+    def __init__(self, parent=None, initpy=[]): 
 +        
         super(Visu, self).__init__(parent)         super(Visu, self).__init__(parent)
         self.setAcceptRichText(False)         self.setAcceptRichText(False)
         self.setLineWrapMode(QtGui.QTextEdit.NoWrap)          self.setLineWrapMode(QtGui.QTextEdit.NoWrap) 
-        # initialisation de la position du curseur dans le texte +         
-        self.pos1 = self.textCursor().position() +        # prépa du lancement du thread qui porte l'interpréteur Python
-        # lancement du thread qui porte l'interpréteur Python+
         self.interpy = Interpy(self)         self.interpy = Interpy(self)
-        self.interpy.start() 
-        # prépa pour recevoir du thread 'interpy' du texte à afficher  
-        self.connect(self.interpy, QtCore.SIGNAL("pourafficher(PyQt_PyObject)"), self.affiche) 
         # prépa pour recevoir de interpy un signal de fermeture de la fenêtre          # prépa pour recevoir de interpy un signal de fermeture de la fenêtre 
         self.connect(self.interpy, QtCore.SIGNAL("finconsole()"), self.quitter)         self.connect(self.interpy, QtCore.SIGNAL("finconsole()"), self.quitter)
 +        # prépa pour recevoir du thread 'interpy' du texte à afficher 
 +        self.affichinit = False
 +        self.connect(self.interpy, QtCore.SIGNAL("pourafficher(PyQt_PyObject)"), self.affiche)
 +        # lancement du thread
 +        self.interpy.start()
 +        
 +        # initialisation de la position du curseur dans le texte
 +        self.pos1 = self.textCursor().position()
 +        
         # initialisation de l'historique des lignes d'instruction Python         # initialisation de l'historique des lignes d'instruction Python
         self.historique = []         self.historique = []
         self.ih = 0         self.ih = 0
-        # initialisation de l'interpréteur +         
-        self.emit(QtCore.SIGNAL("pourlire(PyQt_PyObject)"), u"-*- codingutf-8 -*-"+        prépa de l'initialisation de l'interpréteur si demandé au lancement 
-        self.emit(QtCore.SIGNAL("pourlire(PyQt_PyObject)"), u"from __future__ import division")+        self.initpy = initpy 
 +        if isinstance(self.initpy, (str, unicode))
 +            si c'est une chaineelle doit représenter un fichier à charger 
 +            nfc = self.initpy 
 +            self.initpy = [] 
 +            if os.path.exists(nfc): 
 +                with open(nfc, 'r') as f: 
 +                    for ligne in f: 
 +                        self.initpy.append(ligne.rstrip()) 
 +         
 +        else: 
 +            if not isinstance(self.initpy(list, tuple)): 
 +                # mauvais type pour self.initpy: on n'en tient pas compte 
 +                self.initpy = [] 
 +        self.lginitpy = len(self.initpy) 
 +        self.nbinvites = -1 
 +        
  
 +    
     #========================================================================     #========================================================================
     def affiche(self, texte):     def affiche(self, texte):
         """Affiche la chaine 'texte' dans le widget QTextEdit"""         """Affiche la chaine 'texte' dans le widget QTextEdit"""
 +        global okwrite, mutextokwrite # drapeau pour le shake-hand d'affichage
 +        
         # ajoute la chaine unicode à la fin du QTextEdit         # ajoute la chaine unicode à la fin du QTextEdit
         self.append(texte)         self.append(texte)
Ligne 182: Ligne 239:
         # met à jour la position du curseur dans le texte         # met à jour la position du curseur dans le texte
         self.pos1 = self.textCursor().position()         self.pos1 = self.textCursor().position()
 +        
         # renvoie un accusé de réception de fin d'affichage (shake-hand)         # renvoie un accusé de réception de fin d'affichage (shake-hand)
-        self.interpy.affichageok True +        mutexokwrite.lock() 
-    +        okwrite = True 
 +        mutexokwrite.unlock() 
 +         
 +        # envoie les lignes de code d'initialisation après la 1ère invite 
 +        if self.nbinvites<self.lginitpy: 
 +            if self.nbinvites>=0: 
 +                self.emit(QtCore.SIGNAL("pourlire(PyQt_PyObject)"), self.initpy[self.nbinvites]) 
 +            self.nbinvites += 1 
     # =======================================================================     # =======================================================================
     def keyPressEvent(self, event):     def keyPressEvent(self, event):
Ligne 282: Ligne 348:
          
     #========================================================================     #========================================================================
-    def __init__(self, parent=None):+    def __init__(self, initpy=[], parent=None):
         super(Consolepy, self).__init__(parent)         super(Consolepy, self).__init__(parent)
                  
Ligne 292: Ligne 358:
  
         # créer le QTextEdit personnalisé         # créer le QTextEdit personnalisé
-        self.visu = Visu(self)+        self.visu = Visu(self, initpy)
                  
         # Changer la police de caractères et sa taille         # Changer la police de caractères et sa taille
Ligne 315: Ligne 381:
 ############################################################################# #############################################################################
 if __name__ == '__main__': if __name__ == '__main__':
 +
     app = QtGui.QApplication(sys.argv)     app = QtGui.QApplication(sys.argv)
-    fen = Consolepy()+     
 +    # possibilité de donner comme argument une liste d'instructions Python  
 +    initpy = [u"# -*- coding: utf-8 -*-", 
 +              u"from __future__ import division", 
 +              u"from math import *"] 
 +    # possibilité de donner comme argument un nom de fichier Python à exécuter 
 +    #initpy = "consolepy_init.py" 
 +    # un argument d'un mauvais type ne sera pas considéré (ici un dictionnaire) 
 +    #initpy = {} 
 + 
 +    fen = Consolepy(initpy)
     fen.show()     fen.show()
     sys.exit(app.exec_())     sys.exit(app.exec_())
pyqt4_console_python.txt · Dernière modification: 2013/02/07 13:11 de tyrtamos