我正在为一些长时间运行的控制台进程制作一个进度指示器,意图像这样使用它:
pi = ProgressIndicator()
for x in somelongstuff:
do stuff
pi.update()
pi.print_totals()
基本上,它应该输出某种带点和短划线的进度条,最后输出“234234字节处理”。
我认为将它用作上下文管理器会很好:
with ProgressIndicator() as pi:
for x in somelongstuff:
do stuff
pi.update()
然而,有一些事情让我对这个解决方案感到担忧:
ProgressIndicator
处理循环中可能出现的任何异常这是上下文管理器的有效用例吗?您能提出哪些其他解决方案?
答案 0 :(得分:3)
这绝对是一个有效的用例。如果您不想要它,上下文管理器不必处理异常,尽管您希望结束输出进度条的行以防止它与回溯混淆,并且不打印总计如果通过例外退出。
关于缩进,我认为让用户看到进度实际上是一个非常重要的功能,因此它可以采用缩进级别。
答案 1 :(得分:2)
有一个GUI应用程序,它有一个非常相似的ProgressTask
API,您可以这样使用:
def slow_func():
t = nuke.ProgressTask()
t.setMessage("Doing something")
for x in range(100):
do_something()
t.setProgress(x+1)
调用ProgressTask.__del__
时,进度条UI消失。这在大多数情况下都很好用,但是如果引发异常(例如do_something()
),则回溯对象会保留对ProgressTask
对象的引用,因此进度条会被卡住(直到另一个回溯发生时)
ProgressTask
实现了上下文管理器协议,它可以使用__exit__
方法来确保隐藏进度条。
对于命令行界面(听起来就像你在写),这可能不是问题,但你可以做类似的清理任务,例如显示######### 100% (error)
类型栏,并确保追溯输出没有搞砸等
没有理由你的进度条类无法以两种方式使用 - 大多数上下文管理器完全可用作常规对象和上下文管理器,例如:
lock = threading.Lock()
lock.acquire()
lock.release()
# or:
with lock:
pass