4

我正在为一些长期运行的控制台进程制作进度指示器,并打算像这样使用它:

pi = ProgressIndicator()
for x in somelongstuff:
    do stuff
    pi.update()
pi.print_totals()

基本上,它应该输出某种带有点和破折号的进度条,最后输出类似“234234 bytes processing”的内容。

我认为将它用作上下文管理器会很好:

with ProgressIndicator() as pi:
    for x in somelongstuff:
       do stuff
       pi.update()

然而,关于这个解决方案,我有几件事情让我担心:

  • 额外的缩进使指示器功能看起来比实际更重要
  • 我不想ProgressIndicator处理循环中可能发生的任何异常

这是上下文管理器的有效用例吗?您还能建议哪些其他解决方案?

4

2 回答 2

3

这绝对是一个有效的用例。如果您不想,上下文管理器不必处理异常,尽管您希望结束输出进度条的行以防止它与回溯混淆,并且不打印总数如果它通过异常退出。

关于缩进,我认为让用户看到进度实际上是一个非常重要的功能,因此它可以占用缩进级别。

于 2012-07-04T11:06:04.060 回答
2

有一个 GUI 应用程序,它有一个非常相似的ProgressTaskAPI,你可以像这样使用它:

def slow_func():
    t = nuke.ProgressTask()
    t.setMessage("Doing something")
    for x in range(100):
        do_something()
        t.setProgress(x+1)

ProgressTask.__del__调用时,进度条 UI 消失。这在大多数情况下效果很好,但是如果引发异常(例如 by do_something()),则回溯对象会保留对该ProgressTask对象的引用,因此进度条会卡住(直到发生另一个回溯)

ProgressTask实现了上下文管理器协议,它可以使用该方法__exit__来确保进度条被隐藏。

对于命令行 UI(听起来像您正在编写),这可能不是问题,但您可以执行类似的清理任务,例如显示######### 100% (error)类型栏,并确保回溯输出没有混乱等

没有理由您的进度条类不能以两种方式使用 - 大多数上下文管理器都可以完美地用作常规对象和上下文管理器,例如:

lock = threading.Lock()
lock.acquire()
lock.release()
# or:
with lock:
    pass
于 2012-07-04T11:11:39.257 回答