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

Calcul scientifique Python Discussion :

Lancer un calcul en tâche de fond dans une classe PyQt4


Sujet :

Calcul scientifique Python

  1. #1
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2015
    Messages : 10
    Points : 4
    Points
    4
    Par défaut Lancer un calcul en tâche de fond dans une classe PyQt4
    Bonjour,

    je suis actuellement en train de develloper une application en PyQt. Jusque là j'ai pu me débrouiller pour faire ce que je voulais, mais je n'arrive pas a lancer un calcul en tâche de fond.

    En effet, j'ai un boutton en bas de barre de ma fenêtre principale, qui lance le calcul puis instancie une fenêtre censé montrer à l'utilisateur que le calcul est en cours et sa progression(voir premier bout de code). Le problème est que la fenre n'apparait qu'après la fin du calcul. Je ne sais pas comment régle mon probleme.

    Voila mon code

    the method used when the launch button is clicked in main window to launch the calculation and display the calculation window


    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
      def launchCalc(self):
        #retrieve the RN checked by the user
        self.getRnChoosed()
     
        #print calculation variable
        print "file: "+self.paramDic['filename']
        print "\nSite: "+str(self.paramDic['site'])
        print "\nStart Date: "+self.paramDic['startDate']
        print "\nEnd Date: "+self.paramDic['endDate']
        print "\nAerosols choisis:"+str(self.paramDic['aerosols'])
        print "\nGaz Rares choisis: "+str(self.paramDic['gazRares'])
        print "\nIodes Choisis: "+str(self.paramDic['iodes'])
        print "\nFormat d'export choisis (csv,graphes): "+str(self.paramDic['formatExport(csv,graphe)'])
        print "\nExports choisis: "+str(self.paramDic['exportsChoisis'])
     
        #check that the data are fine to launch calculation
        if len(self.paramDic['aerosols']) == 0 and len(self.paramDic['gazRares']) == 0 and len(self.paramDic['iodes']) == 0:
            QtGui.QMessageBox.warning(self, 'Donnees Invalides',"Vous devez choisir au moins un isotope pour lancer le calcul", QtGui.QMessageBox.Ok)
        elif self.resultPath == '':
            QtGui.QMessageBox.warning(self, 'Erreur',"Vous devez choisir un repertoire contenant la bibliotheque de donnees de resultats Symbiose", QtGui.QMessageBox.Ok)
        #if it's fine launch it
        else:
            self.calcWin = calcWin(self)
            self.calcWin.setWindowModality(QtCore.Qt.ApplicationModal)
            self.calcWin.show()
            launchCalc(self.paramDic,self.resultPath,self.activitiesDic)

    the calcWin class


    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
    class calcWin(QtGui.QWidget):
     
        def __init__(self,appelant):
            super(calcWin, self).__init__()
            self.initUI(appelant)
     
        def initUI(self,appelant):
            self.MWin = appelant
            self.step = 0
            self.VLayout = QtGui.QVBoxLayout()
            self.HLayout = QtGui.QHBoxLayout()
     
            #label
            self.label = QtGui.QLabel('Initialisation des calculs ...')
     
            #bar de progression
            self.pbar = QtGui.QProgressBar(self)
     
            #buttons
            self.btnOk = QtGui.QPushButton('Ok', self)
            self.btnOk.clicked.connect(self.close)
            self.btnOk.setEnabled(False)
     
            self.btnCancel = QtGui.QPushButton('Annuler', self)
            self.btnCancel.clicked.connect(self.cancel)
     
            #mis en place des widget et du layout
            self.VLayout.addWidget(self.label)
            self.VLayout.addWidget(self.pbar)
            self.HLayout.addWidget(self.btnOk)
            self.HLayout.addWidget(self.btnCancel)
            self.VLayout.addLayout(self.HLayout)
     
            self.setLayout(self.VLayout)
     
            #lancement des calculs et mise en forme de la fenetre
            self.setGeometry(300, 300, 280, 170)
            self.setWindowTitle('Calculs en cours')
            self.setWindowIcon(QtGui.QIcon(appelant.AbsPath+'/img/pasta.png'))
     
            #timer pour la mise a jour de la bar de progression
            self.timer = QtCore.QTimer()
            self.timer.start(1000)
            self.timer.timeout.connect(self.update)
     
        def update(self):
            self.pbar.setValue(completion)
            self.timer.start(1000)
     
     
        def cancel(self):
            self.timer.stop()
            self.close()

    the calculation functions

    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
    def launchCalc(paramDic,resultPath,activitiesDic):
        global completion
        completion = completion + 1
        #on crée la liste de tous les RN a traiter
        listRN = paramDic['aerosols']
        listRN.extend(paramDic['gazRares'])
        listRN.extend(paramDic['iodes'])
     
        #on crée les variables bornes du calcul
        delta = datetime.timedelta(hours= 1)
        startDate = fromStringToDate(paramDic['startDate'])
        endDate = fromStringToDate(paramDic['endDate'])
     
        cinetiqueLength = len(activitiesDic[listRN[0]])
        nbPasDeTempsPeriode = int( (endDate - startDate).total_seconds() / 3600 )
        nbPasDeTempsCalcul = nbPasDeTempsPeriode - cinetiqueLength + 1
     
        #on crée le pool de worker
        p = Pool(cpu_count())
     
        # on lance la propagation de la cinetique pour chacun des RN
        time = datetime.datetime.now()
        for RN in listRN:
            completion = int( float(completion) + 100/30)
            p.map(propageCinetique,[ [CAR_to_Symb[RN], startDate + x*delta, resultPath, activitiesDic[RN] ] for x in range(nbPasDeTempsCalcul)])
     
        print datetime.datetime.now()-time
     
     
    def fromStringToDate(string):
        y=int(string.split('/')[2])
        m=int(string.split('/')[1])
        d=int(string.split('/')[0])
        return datetime.datetime(y,m,d)
     
    def formatDate(date):
        return date.strftime("%d-%m-%Y %H:%M:%S")
     
    ################################################################################
     
    def propageCinetique(step):
     
        RN = step[0]
        date = step[1]
        resultPath = step[2]
        coeff = step[3]
        cinetiqueLength = len(coeff)
        tmpPath='/tmp/PASTA/'
        delta = datetime.timedelta(hours= 1)
        # stepTotal=cinetiqueLength*
        print date
     
        if os.path.isdir(tmpPath) == False:
            os.mkdir(tmpPath)
     
        Samples = []
     
        for i in range(cinetiqueLength):
            if (date + i* delta).strftime("%d-%m-%Y %H:%M:%S") in dicDates.keys():
                Samples.append(dicDates[(date + i* delta).strftime("%d-%m-%Y %H:%M:%S")])
            else:
                Samples= []
                break
     
        if Samples != []:
            for index in range(cinetiqueLength):
                if os.path.isfile(tmpPath+date.strftime("%d-%m-%Y@%H")+'.nc'):
                    os.system('ncflint -O -w 1,'+ str(float(coeff[index]) * 3.6) + ' ' + tmpPath + date.strftime('%d-%m-%Y@%H') + '.nc ' +resultPath + '/' + RN + '/'+ Samples[index] +'*/Dose_allPathways.nc ' + tmpPath + date.strftime('%d-%m-%Y@%H') + '.nc ')
                else:
                    os.system('ncflint -w 0,'+ str(float(coeff[index]) * 3.6) + ' ' + resultPath +'/'+ RN + '/'+ Samples[index] +'*/Dose_allPathways.nc ' + resultPath + '/' + RN + '/'+ Samples[index] +'*/Dose_allPathways.nc ' + tmpPath + date.strftime('%d-%m-%Y@%H') + '.nc ')

    J'ai essayé d'utiliser la class QProcess de QtCore pour lancer le calcul en tâche de fond, mais elle de passer seulement des string en arguments de la fonction appelé, ce qui est problématique pour moi ,car mes fonctions de calculs prenne des arguments en entré.

    J'èspere que quelqu'un pourra prendre le temps de se pencher sur mon problème, et je l'en remercie par avance.

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    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 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Dans la mesure où il s'agit de lancer un calcul écrit en Python (et non un programme exécutif externe), je préfère lancer le calcul sous QThread qui est plus souple et qui permet des échanges d'objets Python divers, y compris pendant l'exécution du calcul (pour une barre de progression par exemple).

    Un impératif cependant, facile à respecter, le code du QThread ne doit pas toucher au graphique qui n'est pas "thread-safe". Alors, les échanges entre le programme principal et le thread pendant l'exécution et à la fin se font exclusivement par signaux (emit et connect), et ce sont en fait ces signaux qui transportent les objets de données Python.

    A noter qu'au lieu d'utiliser QThread, on peut aussi utiliser une classe qui hérite en même temps de "threading.Thread" du Python de base, et de "QObject" de PyQt. Et dans cet héritage multiple, c'est le "QObject" qui permet l'émission de signaux.

    Si cette solution QThread t'intéresse, mais que tu rencontres des difficultés, dis-le et je te donnerai un petit code d'exemple.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  3. #3
    Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2015
    Messages : 10
    Points : 4
    Points
    4
    Par défaut
    Merci pour la réponse, et pour la réactivité. Cela m'a beaucoup aidé.

Discussions similaires

  1. Modéliser une tâche de fond dans un UC
    Par rdtech dans le forum Cas d'utilisation
    Réponses: 4
    Dernier message: 09/11/2014, 15h02
  2. Réponses: 7
    Dernier message: 07/03/2012, 09h25
  3. Lancer un programme en tâche de fond sous Windows
    Par FabaCoeur dans le forum Windows
    Réponses: 5
    Dernier message: 15/10/2009, 17h11
  4. Faire une tâche de fond dans un IHM
    Par Charlemagne dans le forum C#
    Réponses: 18
    Dernier message: 06/02/2008, 13h35
  5. Réponses: 6
    Dernier message: 21/09/2006, 17h33

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