在命令提示符中修复Python进度条
我写了下面的代码(在代码审查中已经检查过),目的是在 Python 2.7 中打印一个进度条(顺便说一下,我知道 Python 中有一个 进度条模块)。
from __future__ import division
import sys
class Progress(object):
def __init__(self, maxval):
self._pct = 0
self.maxval = maxval
def update(self, value):
pct = int((value / self.maxval) * 100.0)
if self._pct != pct:
self._pct = pct
self.display()
def start(self):
self.update(0)
def finish(self):
self.update(self.maxval)
def display(self):
sys.stdout.write("|%-100s| %d%%" % ('#' *self._pct, self._pct) + '\n')
sys.stdout.flush()
# test
import time
toolbar_width = 300
pbar = Progress(toolbar_width)
pbar.start()
for i in xrange(toolbar_width):
time.sleep(0.1) # do real work here
pbar.update(i)
pbar.finish()
我希望在我的开发环境中使用这个进度条(比如 Pyscripter、PyCharm 等),还有在命令提示符下使用。当我在命令提示符下运行时,我遇到了两个问题,我不太明白该怎么解决。
- 首先,进度条会打印出限制值(我用了 100s)。
- 其次,进度条会一个接一个地打印出所有的条。我希望在循环中只显示一个进度条,并且这个条会逐渐增加。
3 个回答
1
问题 2: 如果你想在一行中显示一个逐渐增加的进度条,你需要重置光标的位置,这可以通过在 stdout
中写入一个 回车符 来实现。
import sys, time
for x in range(10):
sys.stdout.write((x+1) * '#')
time.sleep(1)
sys.stdout.write("\r") # !!! carriage return sign under Windows !!!
print("Fine")
但是很遗憾:大多数情况下,这在一些集成开发环境(IDE)的标准输出环境中是行不通的
像 Eclipse、PyCharm 等工具会直接读取标准输出,并把变化原样打印到控制台上。
2
问题 1:
你的终端窗口宽度不到 100 个字符,这就是为什么你的进度条看起来超出了限制。其实它只是把输出在 80 个字符处换行了(这是标准的宽度,也是 Windows 控制台的宽度)。
为了避免换行,可以尝试:
sys.stdout.write("|%-50s| %d%%" % ('#' *int(self._pct/2), self._pct) + '\n')
1
1. 可能是因为行太长了,那个终端看起来比100个字符窄。如果你想假设是80个字符(大多数控制台的默认宽度),那么你还有7个字符的其他内容,所以进度条的宽度应该设置为73个字符。
sys.stdout.write("|%-73s| %3d%%" % ('#' * int(self._pct*.73), self._pct) + '\n')
2. 如果想保持在同一行,可以使用 sys.stdout.write
,并且不要在最后加换行符。然后在每行的开头加一个 \r
,这样可以让光标回到行的开头。
sys.stdout.write("\r|%-73s| %3d%%" % ('#' * int(self._pct*.73), self._pct))
你还可以使用 %3d%%
来格式化百分比,这样它就能保持右对齐,一直都是这样。