Question

J'utilise actuellement des générateurs comme moyen rapide de suivre la progression de longs processus et je me demande comment cela se fait habituellement, car je trouve que ce n'est pas très élégant ...

Permettez-moi d’expliquer tout d’abord, j’ai un module engine.py qui effectue un traitement vidéo (segmentation, soustraction bg / fg, etc.) qui prend beaucoup de temps (de quelques secondes à plusieurs minutes).

J'utilise ce module à partir d'une interface graphique écrite en wxpython et d'un script de console. Quand j'ai regardé comment implémenter les dialogues de progression dans wxpython, j'ai compris que je devais obtenir une valeur de progression pour mettre à jour mon dialogue, ce qui est une pure logique que vous admettrez ... J'ai donc décidé d'utiliser le nombre d'images traitées dans les fonctions de mon moteur, d'indiquer le nombre d'images actuel toutes les 33 images et d'obtenir Aucune à l'issue du traitement.

en faisant cela, voici à quoi ça ressemble:

dlg = wx.ProgressDialog("Movie processing", "Movie is being written...",
                           maximum = self.engine.endProcessingFrame,self.engine.startProcessingFrame,
                           parent=self,
                           style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME | wx.PD_SMOOTH | wx.PD_CAN_ABORT)
state = self.engine.processMovie()
f = state.next()
while f != None:
    c, s = dlg.Update(f, "Processing frame %d"%f)
    if not c:break
    f = state.next()
dlg.Destroy()

Cela fonctionne très bien, il n’ya aucune perte de vitesse notable, mais je voudrais pouvoir appeler la fonction processMovie () sans avoir à traiter avec des générateurs si je ne le souhaite pas.

Par exemple, mon script de console qui utilise le module de moteur ne s’intéresse pas à la progression. Je pourrais l’utiliser mais il est destiné à être exécuté dans un environnement sans affichage. Je ne me soucie donc pas de la progression. ...

Quelqu'un avec un autre design que celui que j'ai créé? (en utilisant des threads, des globals, des processus, etc.)

Il doit y avoir une conception quelque part qui fasse ce travail proprement, je pense: :) ??

Était-ce utile?

La solution

Utiliser un générateur convient bien, mais l’intérêt de l’utilisation des générateurs est que vous puissiez utiliser la syntaxe intégrée:

for f in self.engine.processMovie():
    c, s = dlg.Update(f, "Processing frame %d"%f)
    if not c: break

Si cela vous est égal, vous pouvez dire:

for f in self.engine.processMovie(): pass

ou exposer une fonction (par exemple, engine.processMovieFull) pour le faire à votre place.

Vous pouvez également utiliser un rappel en clair:

def update_state(f):
    c, s = dlg.Update(f, "Processing frame %d"%f)
    return c
self.engine.processMovie(progress=update_state)

... mais ce n'est pas aussi bien si vous voulez traiter les données au coup par coup; Les modèles de rappel préfèrent effectuer tout le travail en même temps - c’est le véritable avantage des générateurs.

Autres conseils

Cela ressemble à un cas parfait pour les événements. Le processus envoie un "événement de mise à jour du statut", et toute personne qui souhaite savoir (dans ce cas, la boîte de dialogue) écoute cet événement.

Tout d'abord, si vous utilisez un générateur, vous pouvez aussi bien l'utiliser comme itérateur:

state = self.engine.processMovie()

for f in state:
    c, s = dlg.Update(f, "Processing frame %d"%f)
    if not c:
        break

dlg.Destroy()

Et ne cédez pas Aucun ; arrêtez de céder lorsque vous avez terminé et quittez la fonction; sinon, augmentez StopIteration . C’est la bonne façon de mettre fin à la génération (et lorsqu’on utilise une boucle pour , c’est nécessaire).

À part ça, j'aime bien l'idée. À mon avis, il s’agit d’une utilisation très valable de générateurs.

Vous voudrez peut-être rendre le 33 configurable (c.-à-d. passable à processMovie en tant que paramètre); 33 semble être un choix arbitraire, et si vous traitez un film de deux heures, il n’est pas nécessaire de mettre à jour la barre de progression toutes les 33 images, je suppose.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top