代码之家  ›  专栏  ›  技术社区  ›  attwad

将生成器用作进程通知程序

  •  2
  • attwad  · 技术社区  · 16 年前

    首先让我解释一下,我有一个engine.py模块,它执行一些视频处理(分割、bg/fg减法等),这需要很多时间(从几秒钟到几分钟)。

    我从一个用wxpython编写的GUI和一个控制台脚本中使用这个模块。 因此,我决定在引擎函数中使用已处理的帧数,每33帧生成当前帧数,处理完成后不生成任何帧数。

    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 回复  |  直到 15 年前
        1
  •  2
  •   Glenn Maynard    16 年前

    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)
    

    ... 但如果你想零碎地处理数据,那就没那么好了;回调模型更喜欢一次完成所有工作——这是生成器的真正好处。

        2
  •  1
  •   Lennart Regebro    16 年前

        3
  •  0
  •   balpha    16 年前

    首先,如果使用生成器,还可以将其用作迭代器:

    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