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 :

[PyQt 5] Mise à jour d’une QProgressBar


Sujet :

PyQt Python

  1. #1
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut [PyQt 5] Mise à jour d’une QProgressBar
    Salut à tous !

    Je suis en train de travailler sur une application pour gérer mes entrées et sorties de modèle. Comme j’effectue des traitements un peu long, j’ai besoin de barre de progression.

    En m’inspirant de Progressbar2, j’ai réalisé une classe permettant d’utiliser la barre de progression à travers un itérable. Cependant, si une fenêtre s’ouvre bien, la barre de progression ne s’affiche jamais, comme le montre l’exemple minimum complet suivant (il utilise Python 3 et PyQt 5) :

    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
     
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
     
    """
    Exemple de classe permettant d’utiliser une QProgressBar avec un itérable.
     
    :module: iterableQProgressBar
    :author: Yoann LE BARS
    :version: 1.0
    :date: 16/08/2018
     
    Copyright © 2018 Le Bars, Yoann
     
    This program is distributed under CeCLL-B license, it can be copied and
    modified freely as long as initial author is cited. Complete text
    of CeCILL licence can be found on-line:
     
    <http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html>
    """
     
    import sys
    from PyQt5.QtWidgets import QWidget, QProgressBar, QApplication, QPushButton
     
    class ProgressBar (QWidget):
        """
        Class providing an easy way to use QProgressBar 
        """
     
        def __init__ (self, title, minValue = 0, maxValue = None):
            """
            Class initialiser.
            
            :param title: Window title.
            :param minValue: Minimum value in iteration.
            :param maxValue: Maximum value in iteration.
            """
     
            super().__init__()
            self.setWindowTitle(title)
            self.setGeometry(300, 300, 210, 35)
            # Actual progress bar.
            self._pbar = QProgressBar(self)
            self._pbar.setGeometry(30, 40, 200, 25)
            # Iterable through which iterate.
            self._iterable = None
            # Minimum iteration value.
            self._minValue = minValue
            self._pbar.setMinimum(self._minValue)
            # Maximum iteration value.
            self._maxValue = maxValue
            # Current iteration value.
            self._currValue = self._minValue
            # Whether or not iteration has started.
            self._started = False
     
        def __call__ (self, iterable, maxValue = None):
            """
            Use a ProgressBar to iterate through an iterable.
     
            
            :param iterable: The iterable through which iterate.
            :param maxValue: Maximum value in iteration.
            :return: A pointer to current instance.
            """
     
            if maxValue is None:
                self._maxValue = len(iterable)
            else:
                self._maxValue = maxValue
     
            self._pbar.setMaximum(self._maxValue)
            self._pbar.setValue(self._currValue)
            self._iterable = iter(iterable)
            self.show()
            return self
     
        def __iter__ (self):
            """
            Defines the class as iterable.
     
            :return: A pointer to current instance.
            """
     
            return self
     
        def __next__ (self):
            """
            What to be done every next iteration.
            """
     
            try:
                # New value in iteration.
                value = next(self._iterable)
                if self._started:
                    self._currValue = self._currValue + 1
                else:
                    self._started = True
                    self._currValue = self._minValue
                self._pbar.setValue(self._currValue)
                return value
            except StopIteration:
                raise
     
        def __exit__ (self, exc_type, exc_value, traceback):
            """
            What to do when exiting ProgressBar.
     
            :param exc_type: Type of execution.
            :param exc_value: Execution code.
            :param traceback: Execution trace.
            """
     
            pass
     
        def __enter__ (self):
            """
            What to do when entering ProgressBar.
     
            :return: A pointer to current instance.
            """
     
            return self
     
    class Exemple (QWidget):
        """
        Classe pour la fenêtre principale d’exemple.
        """
     
        def _realiseAction (self):
            """
            Que faire lorsque le bouton est appuyé.
            """
     
            # Iterable pour test.
            liste = [valeur for valeur in range(100000)]
     
            # Barre de progression indiquant l’état d’avancement dans le fichier.
            progression = ProgressBar('Lecture de la liste')
            for valeur in progression(liste):
                print(valeur)
     
        def __init__ (self):
            """
            Initialisation de la fenêtre.
            """
     
            super().__init__()
            self.setGeometry(300, 300, 280, 170)
            self.setWindowTitle('Test de la barre de progression.')
            # Bouton pour lancer l’activité.
            self._btn = QPushButton('Démarrer', self)
            self._btn.move(40, 80)
            self._btn.clicked.connect(self._realiseAction)
            self.show()
     
    if __name__ == '__main__':
        # Instance de l’application.    
        app = QApplication(sys.argv)
        # Fenêtre de test.
        ex = Exemple()
        sys.exit(app.exec_())
    Lorsque l’on appuie sur le bouton « Démarrer », on voit bien apparaître la fenêtre de la barre de progression, mais cette fenêtre est désespérément noire.

    Je pense faire une erreur idiote, mais je ne parviens pas à trouver où se situe le problème. Quelqu’un aurait-il une idée ?

  2. #2
    Expert éminent

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    Que veux-tu faire exactement ?
    Pourquoi ne pas utiliser simplement une QProgressBar et lui envoyer les valeurs au fur et à mesure plutôt que ce code inutile ?

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

    QProgressBar permet d'intégrer une barre de progression dans une fenêtre existante. Mais si on veut simplement une petite fenêtre qui ne contient que la barre de progression, ça existe déjà: QProgressDialog. Voir https://doc.qt.io/qt-5/qprogressdialog.html.

    Une fois ceci fait, le vrai problème est de savoir comment une tâche longue quelconque peut-elle mettre à jour la barre de progression, puisque sans précaution, la tâche longue monopolisera le CPU et bloquera donc le graphique. Une méthode très concise mais un peu brutale sera de forcer le rafraichissement du graphique avec QtCore.QCoreApplication.processEvents(). Mais la méthode que je préfère est de mettre la tâche longue dans un thread (QThread), et de lancer la mise à jour de la barre de progression grâce à des signaux (xxx.emit(...)). Il faut dans ce cas créer un signal pour la mise à jour et un signal pour la fin.

    A noter que la barre de progression nécessite de connaître l'évolution maxi de la valeur. Quand on ne la connait pas, on peut tout de même utiliser la barre de progression, mais en lui demandant d'afficher une "chenille" sans fin, qui ne sera arrêtée qu'à la fin de l'action. Cela permettra simplement d'indiquer à l'utilisateur que l'opération est en cours.
    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

  4. #4
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous*!

    Citation Envoyé par tyrtamos Voir le message
    Mais si on veut simplement une petite fenêtre qui ne contient que la barre de progression, ça existe déjà: QProgressDialog. Voir https://doc.qt.io/qt-5/qprogressdialog.html.
    Merci, j’avais réussi à complètement passer à côté. Ça m’a permis de réduire la quantité de code (voir plus bas), ce qui est toujours une bonne chose.

    Citation Envoyé par tyrtamos Voir le message
    Une fois ceci fait, le vrai problème est de savoir comment une tâche longue quelconque peut-elle mettre à jour la barre de progression, puisque sans précaution, la tâche longue monopolisera le CPU et bloquera donc le graphique. Une méthode très concise mais un peu brutale sera de forcer le rafraichissement du graphique avec QtCore.QCoreApplication.processEvents(). Mais la méthode que je préfère est de mettre la tâche longue dans un thread (QThread), et de lancer la mise à jour de la barre de progression grâce à des signaux (xxx.emit(...)). Il faut dans ce cas créer un signal pour la mise à jour et un signal pour la fin.
    Le code suivant a le comportement attendu. Cependant, il est peut-être possible de faire mieux (j’en parle après) :

    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
     
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
     
    """
    Exemple de classe permettant d’utiliser une QProgressBar avec un itérable.
     
    :module: iterableQProgressBar
    :author: Yoann LE BARS
    :version: 1.0
    :date: 16/08/2018
     
    Copyright © 2018 Le Bars, Yoann
     
    This program is distributed under CeCLL-B license, it can be copied and
    modified freely as long as initial author is cited. Complete text
    of CeCILL licence can be found on-line:
     
    <http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html>
    """
     
    import sys
    from PyQt5.QtWidgets import QWidget, QProgressDialog, QApplication, QPushButton
    from PyQt5 import QtCore
     
    class ProgressBar (QProgressDialog):
        """
        Class providing an easy way to use QProgressDialog.
        """
     
        def __init__ (self, title, minValue = 0, maxValue = None):
            """
            Class initialiser.
            
            :param title: Window title.
            :param minValue: Minimum value in iteration.
            :param maxValue: Maximum value in iteration.
            """
     
            super().__init__(title, None, minValue, 0)
    #        self.setWindowModality(QtCore.Qt.WindowModal)
            if maxValue is not None:
                self.setMaximum(maxValue)
            # Iterable through which iterate.
            self._iterable = None
            self.setValue(self.minimum())
            self.setWindowTitle('Progression')
            # Whether or not iteration has started.
            self._started = False
     
        def __call__ (self, iterable, maxValue = None):
            """
            Use a ProgressBar to iterate through an iterable.
     
            
            :param iterable: The iterable through which iterate.
            :param maxValue: Maximum value in iteration.
            :return: A pointer to current instance.
            """
     
            if maxValue is None:
                self.setMaximum(len(iterable))
            else:
                self.setMaximum(maxValue)
     
            self._iterable = iter(iterable)
            self.show()
            return self
     
        def __iter__ (self):
            """
            Defines the class as iterable.
     
            :return: A pointer to current instance.
            """
     
            return self
     
        def __next__ (self):
            """
            What to be done every next iteration.
            """
     
            try:
                # New value in iteration.
                iter = next(self._iterable)
                if self.wasCanceled():
                    raise StopIteration ()
                if self._started:
                    self.setValue(self.value() + 1)
                else:
                    self._started = True
                    self.setValue(self.minimum())
                QtCore.QCoreApplication.processEvents()
                return iter
            except StopIteration:
                self._started = False
                self.setValue(self.maximum())
                self.cancel()
                QtCore.QCoreApplication.processEvents()
                raise
     
        def __exit__ (self, exc_type, exc_value, traceback):
            """
            What to do when exiting ProgressBar.
     
            :param exc_type: Type of execution.
            :param exc_value: Execution code.
            :param traceback: Execution trace.
            """
     
            pass
     
        def __enter__ (self):
            """
            What to do when entering ProgressBar.
     
            :return: A pointer to current instance.
            """
     
            return self
     
        def reset (self, title, valMin = 0, valMax = None):
            """
            Reset progress bar.
     
            :param title: New window title.
            :param valMin: Minimum value during progress.
            :param valMax: Maximum value during progress.
            """
     
            super().reset()
            self.setLabelText(title)
            self.setMinimum(valMin)
            if valMax is not None:
                self.setMaximum(valMax)
            self.setValue(valMin)
            self._started = False
     
    class Exemple (QWidget):
        """
        Classe pour la fenêtre principale d’exemple.
        """
     
        def _realiseAction (self):
            """
            Que faire lorsque le bouton est appuyé.
            """
     
            # Barre de progression indiquant l’état d’avancement de l’activité.
            progression = ProgressBar('Création de la liste')
            # Iterable pour test.
            liste = [valeur for valeur in progression(range(100000))]
     
            progression.reset('Lecture de la liste')
            for valeur in progression(liste):
                print(valeur)
     
        def __init__ (self):
            """
            Initialisation de la fenêtre.
            """
     
            super().__init__()
            self.setGeometry(300, 300, 280, 170)
            self.setWindowTitle('Test de la barre de progression.')
            # Bouton pour lancer l’activité.
            self._btn = QPushButton('Démarrer', self)
            self._btn.move(40, 80)
            self._btn.clicked.connect(self._realiseAction)
            self.show()
     
    if __name__ == '__main__':
        # Instance de l’application.    
        app = QApplication(sys.argv)
        # Fenêtre de test.
        ex = Exemple()
        sys.exit(app.exec_())
    En l’espèce, ajouter une structure de processus léger me semble une complication inutile. En revanche, en lisant la documentation, il m’a semblé qu’en définissant la fenêtre en tant que « WindowModal », il n’était pas nécessaire de forcer le traitement des évènements. J’ai laissé ma tentative en commentaire pour montrer comment j’avais fait, mais ça n’a rien donné.

    Du coup, j’ai placé deux « processEvents ». Je ne sais pas si ça pose problème, je suis donc preneur de toutes remarques concernant la qualité du code.

    Citation Envoyé par VinsS Voir le message
    Que veux-tu faire exactement ?
    Confère les deux exemples dans la classe de test du code que j’ai posté : cela permet de créer simplement des barres de progressions au travers d’itérateurs. D’une part, dans la mesure où mon application est basée sur un modèle de greffons, cela permet à la fois d’harmoniser l’apparence dans l’application, mais également de permettre à chaque développeur de greffon d’utiliser facilement une barre de progression et donc de le faire, quelque soit son niveau de programmation et de connaissance de Qt.

    Par ailleurs, l’application utilise souvent des fonctions internes de Python, typiquement les fonctions d’interpolations. En passant par ce système qui est appelé automatiquement à chaque nouvelle itération, cela permet d’avoir une barre de progression efficace même avec une fonction qui est une boîte noire.

    À bientôt.

  5. #5
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    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 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par Le Farfadet Spatial Voir le message
    En l’espèce, ajouter une structure de processus léger me semble une complication inutile
    Garde tout de même l'idée: tu y reviendras pour des raisons de qualité de fonctionnement.
    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

  6. #6
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    J’ai fini par trouver comment déclarer la fenêtre de progression comme modale. Du coup, j’en suis au code suivant :

    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
     
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
     
    """
    Exemple de classe permettant d’utiliser une QProgressBar avec un itérable.
     
    :module: iterableQProgressBar
    :author: Yoann LE BARS
    :version: 1.0
    :date: 16/08/2018
     
    Copyright © 2018 Le Bars, Yoann
     
    This program is distributed under CeCLL-B license, it can be copied and
    modified freely as long as initial author is cited. Complete text
    of CeCILL licence can be found on-line:
     
    <http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html>
    """
     
    import sys
    from PyQt5.QtWidgets import QWidget, QProgressDialog, QApplication, QPushButton
    #from PyQt5 import QtCore
     
    class ProgressBar (QProgressDialog):
        """
        Class providing an easy way to use QProgressDialog.
        """
     
        def __init__ (self, title, minValue = 0, maxValue = None):
            """
            Class initialiser.
            
            :param title: Window title.
            :param minValue: Minimum value in iteration.
            :param maxValue: Maximum value in iteration.
            """
     
            super().__init__(title, None, minValue, 0)
            self.setMinimumDuration(0)
            self.setModal(True)
            if maxValue is not None:
                self.setMaximum(maxValue)
            # Iterable through which iterate.
            self._iterable = None
            self.setValue(self.minimum())
            self.setWindowTitle('Progression')
            # Whether or not iteration has started.
            self._started = False
     
        def __call__ (self, iterable, maxValue = None):
            """
            Use a ProgressBar to iterate through an iterable.
     
            
            :param iterable: The iterable through which iterate.
            :param maxValue: Maximum value in iteration.
            :return: A pointer to current instance.
            """
     
            if maxValue is None:
                self.setMaximum(len(iterable))
            else:
                self.setMaximum(maxValue)
     
            self._iterable = iter(iterable)
            self.show()
            return self
     
        def __iter__ (self):
            """
            Defines the class as iterable.
     
            :return: A pointer to current instance.
            """
     
            return self
     
        def __next__ (self):
            """
            What to be done every next iteration.
            """
     
            try:
                # New value in iteration.
                iter = next(self._iterable)
                if self.wasCanceled():
                    raise StopIteration ()
                if self._started:
                    self.setValue(self.value() + 1)
                else:
                    self._started = True
                    self.setValue(self.minimum())
    #            QtCore.QCoreApplication.processEvents()
                return iter
            except StopIteration:
                self._started = False
                self.setValue(self.maximum())
                self.cancel()
    #            QtCore.QCoreApplication.processEvents()
                raise
     
        def __exit__ (self, exc_type, exc_value, traceback):
            """
            What to do when exiting ProgressBar.
     
            :param exc_type: Type of execution.
            :param exc_value: Execution code.
            :param traceback: Execution trace.
            """
     
            pass
     
        def __enter__ (self):
            """
            What to do when entering ProgressBar.
     
            :return: A pointer to current instance.
            """
     
            return self
     
        def reset (self, title, valMin = 0, valMax = None):
            """
            Reset progress bar.
     
            :param title: New window title.
            :param valMin: Minimum value during progress.
            :param valMax: Maximum value during progress.
            """
     
            super().reset()
            self.setLabelText(title)
            self.setMinimum(valMin)
            if valMax is not None:
                self.setMaximum(valMax)
            self.setValue(valMin)
            self._started = False
     
    class Exemple (QWidget):
        """
        Classe pour la fenêtre principale d’exemple.
        """
     
        def _realiseAction (self):
            """
            Que faire lorsque le bouton est appuyé.
            """
     
            # Barre de progression indiquant l’état d’avancement de l’activité.
            progression = ProgressBar('Création de la liste')
            # Iterable pour test.
            liste = [valeur for valeur in progression(range(100000))]
     
            progression.reset('Lecture de la liste')
            for valeur in progression(liste):
                print(valeur)
     
        def __init__ (self):
            """
            Initialisation de la fenêtre.
            """
     
            super().__init__()
            self.setGeometry(300, 300, 280, 170)
            self.setWindowTitle('Test de la barre de progression.')
            # Bouton pour lancer l’activité.
            self._btn = QPushButton('Démarrer', self)
            self._btn.move(40, 80)
            self._btn.clicked.connect(self._realiseAction)
            self.show()
     
    if __name__ == '__main__':
        # Instance de l’application.    
        app = QApplication(sys.argv)
        # Fenêtre de test.
        ex = Exemple()
        sys.exit(app.exec_())
    Avec un tel code, je laisse le fonctionnement interne de Qt se charger de toute la mise à jour des fenêtres. De ce que j’ai pu trouver par ailleurs sur le web, cela semble être une façon assez standard de gérer une barre de progression dans une boucle simple – sachant que le code que je présente est pour gérer une barre de progression dans un itérateur, cela signifie que je ne me place que dans le cas de boucles simples.

    Citation Envoyé par tyrtamos Voir le message
    Garde tout de même l'idée: tu y reviendras pour des raisons de qualité de fonctionnement.
    Je suis tout prêt à le croire, mais avec le code que je présente dans ce message, je laisse Qt s’occuper des évènements en interne. Par ailleurs, sur l’application sur laquelle je travaille, typiquement l’utilisateur n’a aucun intérêt à interagir avec l’application tant que le traitement demandé n’est pas achevé. Il a même plutôt intérêt à ne pas interagir pour éviter de créer des artefacts.

    Par ailleurs, dans la mesure où ma classe est créée pour être utilisée dans les itérations d’un itérateur, cela veut dire qu’il faut que je me débrouille, dans la fonction « __init__ » de la classe « ProgressBar », pour placer les itérations dans un processus léger, sachant que je ne peux pas présumer autre chose sur ce processus qu’il s’agit d’itérations. Du coup, je ne vois pas comment faire.

    Si le mode modal existe dans Qt, c’est bien parce qu’il y a des cas où il est parfaitement approprié, non ? À l’inverse, les processus légers ne sont pas une panacée à utiliser quel que soit le cas, sans se demander s’ils sont bien ce qu’il faut pour une tâche précise.

    Bref : je suis disposé à croire que je sois dans un cas où les processus légers sont appropriés, mais j’ai besoin d’arguments l’indiquant. Par ailleurs, pour réaliser des processus légers à partir d’une classe itérable, j’ai besoin d’être guidé. Donc, s’il y a plus d’éléments sur la question, je suis preneur.

    À bientôt.

  7. #7
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    J’imagine que s’il n’y a pas eu de réponse, c’est que personne n’a rien de particulier à dire sur le sujet. Au cas où, avant de clore la discussion, je tente d’abord de la faire remonter.

    À bientôt.

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

    Pour expliciter comment je fais pour mettre à jour une barre de progression avec un thread, voilà un petit code de principe avec QProgressDialog:

    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    # Python 3.5, PyQt 5.9
     
    """
    modèle pour progression en % d'une tâche longue avec callback qui
    s'exécute dans un thread
    """
     
    import sys
    from PyQt5 import (QtWidgets, QtCore)
     
    # pour la simulation d'une tâche longue
    from time import time, sleep
     
    #############################################################################
    def action(callback=None):
        """action qui dure 5 secondes mais qui renvoie un % d'avancement
           en appelant la méthode callback
        """
        delai = 5  # delai de 5 secondes
        t0 = time()  # temps initial
        while True:
            tempspasse = time() - t0
            if callback != None:
                callback(tempspasse / delai)  # envoi du % d'avancement
            if tempspasse > delai:
                break  # délai dépassé
            sleep(0.1)  # simulation d'un temps de traitement
     
    #############################################################################
    class Monthread(QtCore.QThread):
     
        # création d'un nouveau signal pour info du % d'avancement
        progduthread = QtCore.pyqtSignal(float)
        # création d'un nouveau signal pour info de la fin du thread
        finduthread = QtCore.pyqtSignal(str)
     
        #========================================================================
        def __init__(self, parent=None):
            super().__init__(parent)
     
        #========================================================================
        def run(self):
            # lancement d'une tâche qui dure 5 secondes (5 sec)
            action(self.avancement)
            # fin normale du thread
            self.finduthread.emit("Fin de l'action")
     
        #========================================================================
        def avancement(self, pourc):
            """méthode lancée pendant l'action avec callback
            """
            # envoi du % d'avancement pour mise à jour de la barre de progression
            self.progduthread.emit(pourc)
     
    #############################################################################
    class Fenetre(QtWidgets.QWidget):
     
        #========================================================================
        def __init__(self, parent=None):
            super().__init__(parent)
            self.resize(300, 200)
     
            # bouton qui exécute la méthode action
            self.bouton = QtWidgets.QPushButton("début", self)
            self.bouton.clicked.connect(self.action)
     
            # position du bouton dans la fenêtre
            posit = QtWidgets.QGridLayout()
            posit.addWidget(self.bouton, 0, 0)
            self.setLayout(posit)
     
            # création des variables définies plus tard
            self.monthread = None
            self.prog = None
     
        #========================================================================
        def action(self):
            """méthode lancée par le bouton pour démarrer ou stopper une
               opération longue dans un thread
            """
            if self.monthread == None or not self.monthread.isRunning():
                # => démarrage de l'action dans le thread
     
                # création du QProgressDialog
                self.prog = QtWidgets.QProgressDialog("En cours...", "Annuler", 0, 100, self)
                self.prog.setWindowTitle("Action")
                # branchement du bouton "annuler" à la méthode 'stopaction'
                self.prog.canceled.connect(self.stopaction)
                # affichage de la fenêtre de progression
                self.prog.show()
     
                # lancement du thread avec son opération
                self.monthread = Monthread()
                # se préparer à recevoir le % d'avancement
                self.monthread.progduthread.connect(self.progression)
                # se préparer à recevoir le signal de fin du thread
                self.monthread.finduthread.connect(self.finaction)
                # démarrer le thread
                self.monthread.start()
                # surtout pas de "self.monthread.join()" ici!!!
     
                # changement du texte du bouton
                self.bouton.setText("Stop")
     
            else:
                # => arrêt du thread avant la fin, demandé par le bouton "Stop"
                self.stopaction()
     
        #========================================================================
        def progression(self, pourc):
            """mise à jour de la barre de progression
            """
            self.prog.setValue(pourc * 100)
            if pourc >= 100:
                self.prog.reset()
     
        #========================================================================
        def stopaction(self):
            """méthode lancée par le bouton "annuler" de la fenêtre de progression
            """
            # arrêt brutal du thread
            self.monthread.terminate()
            # arrêt de la fenêtre de progression
            self.prog.reset()
            # retour au texte initial du bouton
            self.bouton.setText("Début")
     
        #========================================================================
        def finaction(self, msg):
            """méthode lancée à la fin normale du thread
            """
            # arrêt de la fenêtre de progression
            self.prog.reset()
            # retour au texte initial du bouton
            self.bouton.setText("Début")
            # affichage du message de fin
            QtWidgets.QMessageBox.information(self,
                "Information",
                msg)
     
    #############################################################################
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())
    A prendre par copier-coller et exécuter pour voir.

    Il est vrai que je travaille avec les threads depuis longtemps, et que je choisis facilement cette solution qui marche très bien. Tu as le droit de ne pas être d'accord.
    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

  9. #9
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    Citation Envoyé par tyrtamos Voir le message
    Pour expliciter comment je fais pour mettre à jour une barre de progression avec un thread, voilà un petit code de principe avec QProgressDialog:
    Merci, c’est toujours bon à prendre. Cela dit, ça ne règle pas mon problème*: je passe par un itérable, il faudrait donc que je place les itérations dans un processus léger et je ne vois pas comment le faire.

    Citation Envoyé par tyrtamos Voir le message
    Il est vrai que je travaille avec les threads depuis longtemps, et que je choisis facilement cette solution qui marche très bien. Tu as le droit de ne pas être d'accord.
    Dans l’immédiat, je ne suis ni d’accord, ni pas d’accord. Je ne vois surtout pas comment faire autrement. Par ailleurs, je manque d’expérience avec les processus légers de Qt, je ne suis pas vraiment au fait de ses avantages et inconvénients.

    À bientôt.

  10. #10
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    Bon, je pense que s’il n’y a plus de réponse, c’est que personne n’a de solution à proposer pour placer les itérations dans un processus léger. Cela dit, encore une fois, avant de clore définitivement ce fil de discussion, je le fais remonter.

    À bientôt.

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

    Citation Envoyé par Le Farfadet Spatial Voir le message
    c’est que personne n’a de solution à proposer pour placer les itérations dans un processus léger.
    Je ne comprends pas la difficulté que tu rencontres avec ça. Si ta tâche longue se fait sur la base d'itération, tu intègres l'itération dans la méthode "run" du thread (celle qui est lancée par "start()"). Et si au lancement du thread tu sais combien d'itérations il y aura, tu as ce qu'il faut pour mettre à jour la barre de progression: à chaque itération, ton thread enverra par ".emit(...)" au graphique l'info de progression.
    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

  12. #12
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    Citation Envoyé par tyrtamos Voir le message
    Je ne comprends pas la difficulté que tu rencontres avec ça. Si ta tâche longue se fait sur la base d'itération, tu intègres l'itération dans la méthode "run" du thread (celle qui est lancée par "start()"). Et si au lancement du thread tu sais combien d'itérations il y aura, tu as ce qu'il faut pour mettre à jour la barre de progression: à chaque itération, ton thread enverra par ".emit(...)" au graphique l'info de progression.
    Confère le code que j’ai donné. Voici comment est créée et appelée la barre de progression :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    # Barre de progression indiquant l’état d’avancement de l’activité.
    progression = ProgressBar('Création de la liste')
    # Iterable pour test.
    liste = [valeur for valeur in progression(range(100000))]
    Ce qui appelle le code de mise à jour de la barre de progression, ce sont les itérations de la compréhension de liste. Or, il faut que je crée le processus léger dans le code de la classe « ProgressBar ». La seule solution que je vois, c’est de placer tant les itérations que la mise à jour de la barre dans le même processus léger, ce qui ne me semble pas avoir d’intérêt.

    Typiquement, voici comment j’utilise « ProgressBar » dans le code de mon application :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    # Progress bar title.
    pBarTitle = self._translate('PlotComp', 'Getting computed values in solution {}.')
    # Progress bar indicating advancement computations.
    pBar = PluginsUtils.ProgressBar(pBarTitle.format(sNumber))
    # Computed values.
    cValues = [interpolate.griddata(points, values[i], (x0, y0), method = 'cubic') for i in pBar(range(cFile.dimensions['time'].size))]
    La fonction « interpolate » est une fonction de SciPy, c’est une boîte noire. De toute façon, ne pas passer par une compréhension de liste serait totalement inefficace, d’autant que le jeu de données (contenu dans un fichier au format NetCDF) est assez lourd. En conséquence, je ne peux pas passer par une boucle « for », il faut impérativement que la mise à jour de la barre de progression soit réalisée par les appels à l’itérateur. Or, dans un tel code (la classe « ProgressBar » que j’ai donnée correspond au code de mon application), je ne vois pas comment faire pour placer les itérations dans un autre processus léger que celui de la mise à jour de la barre de progression.

    À bientôt.

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

    Tu es coincé parce que tu as mélangé l'itérateur et la barre de progression: je ne vois aucune raison de faire ça.

    Voilà un code de principe:

    J'ai créé un itérateur "Iterateur" qui fait à peu près ce que fait range.

    J'ai un thread qui pilote l'action longue qui contient l'itérateur, et qui envoie sous forme de signaux l'info de mise à jour de la barre de progression, et la fin du thread.

    Et enfin, la partie graphique, qui lancera le thread, mettra à jour la barre de progression et l'arrêtera à la fin du thread.

    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
     
    import sys
    from PyQt5 import (QtWidgets, QtCore)
     
    # pour la simulation d'une tâche longue
    from time import sleep
     
    ##############################################################################
    class Iterateur(object):
     
        def __init__(self, deb, fin=None, pas=None):
            if pas==None:
                if fin==None:
                    # 1 seul paramètre
                    self.deb, self.fin, self.pas = 0, deb, 1
                else:
                    # 2 paramètres
                    self.deb, self.fin, self.pas = deb, fin, 1
            else:
                # 3 paramètres
                self.deb, self.fin, self.pas = deb, fin, pas
     
            self.cpt = self.deb  # initialisation du compteur
     
        def __iter__(self):
            return self
     
        def __next__(self): # => "next" pour Python2 et "__next__" pour Python3
            if self.cpt >= self.fin:
                raise StopIteration
            k = self.cpt
            self.cpt += self.pas  # incrementation du compteur pour le prochain appel
            return k 
     
    #############################################################################
    class Monthread(QtCore.QThread):
     
        # création d'un nouveau signal pour info du % d'avancement
        progduthread = QtCore.pyqtSignal(float)
        # création d'un nouveau signal pour info de la fin du thread
        finduthread = QtCore.pyqtSignal(str)
     
        #========================================================================
        def __init__(self, parent=None):
            super().__init__(parent)
     
        #========================================================================
        def run(self):
            # nb d'itération prévue
            nmax = 100
            # lancement d'une tâche longue
            for i in Iterateur(nmax):
                # simule une tâche de calcul longue
                sleep(0.1) 
                # envoi de l'info de progression au graphique
                self.progduthread.emit((i+1)/100)
     
            # signale que le thread est terminé
            self.finduthread.emit("Fin de l'action")
     
    #############################################################################
    class Fenetre(QtWidgets.QWidget):
     
        #========================================================================
        def __init__(self, parent=None):
            super().__init__(parent)
            self.resize(300, 200)
     
            # bouton qui exécute la méthode action
            self.bouton = QtWidgets.QPushButton("début", self)
            self.bouton.clicked.connect(self.action)
     
            # position du bouton dans la fenêtre
            posit = QtWidgets.QGridLayout()
            posit.addWidget(self.bouton, 0, 0)
            self.setLayout(posit)
     
            # création des variables définies plus tard
            self.monthread = None
            self.prog = None
     
        #========================================================================
        def action(self):
            """méthode lancée par le bouton pour démarrer ou stopper une
               opération longue dans un thread
            """
            if self.monthread == None or not self.monthread.isRunning():
                # => démarrage de l'action dans le thread
     
                # création du QProgressDialog
                self.prog = QtWidgets.QProgressDialog("En cours...", "Annuler", 0, 100, self)
                self.prog.setWindowTitle("Action")
                # branchement du bouton "annuler" à la méthode 'stopaction'
                self.prog.canceled.connect(self.stopaction)
                # affichage de la fenêtre de progression
                self.prog.show()
     
                # lancement du thread avec son opération
                self.monthread = Monthread()
                # se préparer à recevoir le % d'avancement
                self.monthread.progduthread.connect(self.progression)
                # se préparer à recevoir le signal de fin du thread
                self.monthread.finduthread.connect(self.finaction)
                # démarrer le thread
                self.monthread.start()
                # surtout pas de "self.monthread.join()" ici!!!
     
                # changement du texte du bouton
                self.bouton.setText("Stop")
     
            else:
                # => arrêt du thread avant la fin, demandé par le bouton "Stop"
                self.stopaction()
     
        #========================================================================
        def progression(self, pourc):
            """mise à jour de la barre de progression
            """
            self.prog.setValue(pourc * 100)
            if pourc >= 100:
                self.prog.reset()
     
        #========================================================================
        def stopaction(self):
            """méthode lancée par le bouton "annuler" de la fenêtre de progression
            """
            # débranchement des liens
            self.monthread.progduthread.disconnect()
            self.monthread.finduthread.disconnect()
            # arrêt brutal du thread
            self.monthread.terminate()
            # arrêt de la fenêtre de progression
            self.prog.reset()
            # retour au texte initial du bouton
            self.bouton.setText("Début")
     
        #========================================================================
        def finaction(self, msg):
            """méthode lancée à la fin normale du thread
            """
            # arrêt de la fenêtre de progression
            self.prog.reset()
            # retour au texte initial du bouton
            self.bouton.setText("Début")
            # affichage du message de fin
            QtWidgets.QMessageBox.information(self,
                "Information",
                msg)
     
    #############################################################################
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())
    A noter que si le nb d'itération n'est pas connu au départ, tu n'as plus de progression possible. Il te reste à faire que la barre de progression affiche une "chenille" qui dira simplement à l'utilisateur que le travail est en cours. Pour la configuration, il suffit de donner une plage [0, 0] ) à la barre de progression. On peut d'ailleurs changer si nécessaire la forme de la chenille!
    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

  14. #14
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    Citation Envoyé par tyrtamos Voir le message
    Tu es coincé parce que tu as mélangé l'itérateur et la barre de progression: je ne vois aucune raison de faire ça.
    Ça me permet de ne pas faire de boucle « for ». J’ai déjà testé avec une boucle « for », non seulement c’est beaucoup moins efficace, mais en plus le processus n’arrive jamais à son terme : après avoir saturé la mémoire, le processus est tué – cela tient sans doute également à la façon d’accéder aux fichiers NetCDF, qui, si jamais c’est réalisé sans précaution, peut vite surcharger la mémoire. À l’inverse, mes tests montrent qu’en passant par une compréhension de liste, non seulement le processus arrive à son terme, mais en plus le temps de traitement est parfaitement acceptable. Il est de toute façon nécessaire de passer par une compréhension de liste.

    Évidemment, j’ai présenté ici un code simple pour juste présenter la partie qui pose problème. Il est certain que remplir une liste des cent mille premiers entiers n’est pas une tâche complexe. Cependant, dans mon cas concret, j’interpole des données sur un maillage représentant une surface de plusieurs milliers de kilomètres carrés. Je suis dans un cas où il importe de se soucier des performances.

    Citation Envoyé par tyrtamos Voir le message
    Voilà un code de principe:
    Merci pour ce code, c’est du travail. J’apprécie vraiment.

    Cependant, à moins que j’ai mal compris, il implique de passer par une boucle « for » (comme on le voit dans la méthode « run » de la classe « Monthread »). C’est d’ailleurs bien la solution que j’ai trouvée de mon côté pour réaliser un processus léger. Cette solution ne permet pas de faire une compréhension de liste et je ne peux donc pas l’utiliser.

    Bien entendu, plutôt que de faire une compréhension de liste, on peut théoriquement passer par une boucle et émettre un signal à chaque itération. Cependant, c’est beaucoup moins efficace qu’en passant par une compréhension de liste. Tellement moins efficace que, comme dit, dans mon cas particulier le traitement n’arrive jamais à terme. Sachant que pour l’instant je teste avec des fichiers considérés comme contenant peu de données…

    Après, il y a toujours la possibilité de passer par du code C++. Cependant, même si je maîtrise mieux C++ que Python, je préférerais éviter d’en passer par là, car ça rendrait l’infrastructure de l’application beaucoup plus complexe. D’autant que, comme déjà mentionné, avec une compréhension de liste les performances sont parfaitement acceptable.

    Donc, il reste sur le problème que je dois impérativement passer par une compréhension de liste et mettre à jour ma barre de progression. C’est la raison pour laquelle je me suis basé sur le code de Progressbar2.

    À bientôt.

  15. #15
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    Pour ma part, je n’ai pas trouvé d’autre moyen de réaliser une compréhension de liste tout en créant un processus léger. A priori, on ne peut pas le faire avec l’approche que j’ai choisie. En ce qui me concerne, je ne vois pas d’autre moyen de réaliser une barre de progression tout en passant par une compréhension de liste.

    Je pense que si personne n’a proposé une autre solution, c’est que personne ne sait comment réaliser cela – si même c’est possible. À tout hasard, je tente de relancer une dernière fois ce sujet de discussion avant de le passer définitivement en résolu.

    À bientôt.

  16. #16
    Membre confirmé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 186
    Points : 604
    Points
    604
    Par défaut
    Salut à tous !

    Très bien, je considère donc qu’il n’y a plus rien à dire sur le sujet, que je passe donc en résolu. Encore merci pour l’aide, Tyrtamos.

    À bientôt.

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

Discussions similaires

  1. [MySQL] Mise à jour mysql avec une checkbox non checké
    Par lodan dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 24/08/2006, 16h45
  2. [Conception] mise à jour automatique d'une base de donné distante
    Par bipbip2006 dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 01/06/2006, 16h45
  3. Requête Mise à jour à partir d'une autre table
    Par temar dans le forum Access
    Réponses: 2
    Dernier message: 17/05/2006, 09h23
  4. Mise à jour automatique d'une table access via un .xls
    Par infratunes dans le forum Access
    Réponses: 4
    Dernier message: 05/04/2006, 18h33
  5. [VS2003][VB.NET]Mise à jour DataSet d'une grille (erreur)
    Par m-mas dans le forum Windows Forms
    Réponses: 2
    Dernier message: 08/02/2006, 10h41

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