использование генераторов в качестве уведомителя о прогрессии - PullRequest
2 голосов
/ 31 июля 2009

В настоящее время я использую генераторы как быстрый способ получения прогресса в длительных процессах, и мне интересно, как это обычно делается, так как я нахожу это не очень элегантным ...

Позвольте мне сначала объяснить, у меня есть модуль engine.py, который выполняет некоторую обработку видео (сегментацию, вычитание bg / fg и т. Д.), Которая занимает много времени (от секунд до нескольких минут).

Я использую этот модуль из графического интерфейса, написанного на wxpython и консольного скрипта. Когда я посмотрел, как реализовать диалоги прогресса в wxpython, я увидел, что мне нужно каким-то образом получить значение прогресса для обновления моего диалога, что является чистой логикой, которую вы признаете ... Поэтому я решил использовать количество кадров, обработанных в моих функциях движка, выводить текущий номер кадра каждые 33 кадра и выводить None после завершения обработки.

* * * * * * *

, делая это вот так:

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()

Это работает очень хорошо, заметных потерь скорости нет, но я бы хотел иметь возможность вызывать функцию processMovie () без необходимости работать с генераторами, если я этого не хочу.

Например, мой консольный скрипт, который использует модуль движка, не заботится о прогрессе, я мог бы использовать его, но он предназначен для выполнения в среде, где нет отображения, так что мне действительно все равно, как работает ...

Кто-нибудь с другим дизайном, который я придумал? (используя потоки, глобалы, процессы и т. д.)

Где-то должен быть дизайн, который делает эту работу чище, я думаю: -)

Ответы [ 3 ]

2 голосов
/ 31 июля 2009

Использование генератора прекрасно для этого, но весь смысл использования генераторов заключается в том, что вы можете встроить синтаксис:

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

Если вас это не волнует, вы можете сказать:

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

или предоставьте функцию (например, engine.processMovieFull), чтобы сделать это для вас.

Вы также можете использовать простой обратный вызов:

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

... но это не так хорошо, если вы хотите обрабатывать данные по частям; Модели обратного вызова предпочитают выполнять всю работу одновременно - это реальная выгода генераторов.

1 голос
/ 31 июля 2009

Это звучит как идеальный случай для событий. Процесс отправляет «событие обновления статуса», и любой, кто хочет знать (в данном случае диалоговое окно), слушает это событие.

0 голосов
/ 31 июля 2009

Прежде всего, если вы используете генератор, вы можете использовать его как итератор:

state = self.engine.processMovie()

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

dlg.Destroy()

И не поддавайтесь None; прекратите уступать, когда закончите, и выйдите из функции; альтернативно поднять StopIteration. Это правильный способ завершения генерации (и при использовании цикла for это необходимо).

Кроме этого, мне нравится идея. На мой взгляд, это очень правильное использование генераторов.

Возможно, вы захотите сделать 33 конфигурируемым (то есть передаваемым processMovie в качестве параметра); 33 кажется произвольным выбором, и если вы обрабатываете двухчасовой фильм, то нет необходимости обновлять индикатор выполнения каждые 33 кадра, я думаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...