Вы должны сделать три вещи:
- сохранить состояние индикатора выполнения в отдельном объекте, для которого вы можете вызывать методы для обновления состояния панели в разных циклах.
- при печатииндикатор выполнения, убедитесь, что при выводе на консоль выводится новая строка
- , сначала очистите текущую строку, а затем заново отрисуйте строку после печати.
Вы покрываете первые два, несколько, но не третий.Вероятно, лучше всего инкапсулировать управление консолью в классе, который также управляет индикатором выполнения, чтобы он мог выполнять очистку, печать и повторное отображение всего в одном месте:
import builtins
import math
import sys
import threading
class ProgressConsole:
def __init__(self, size, width=80, output=sys.stdout):
self.size = size
self.width = width
self.current = 0
self.output = output
# [...] and space take 3 characters, plus max width of size (log10 + 1)
self._bar_size = width - 4 - int(math.log10(size))
self._bar_step = self._bar_size / self.size
self._lock = threading.Lock()
def print(self, *message):
with self._lock:
self._clear()
builtins.print(*message, file=self.output)
self._display()
def increment(self, step=1):
with self._lock:
self.current = min(self.current + step, self.size)
self._display()
def _clear(self):
self.output.write('\r')
self.output.write(' ' * self.width)
self.output.write('\r')
def _display(self):
bar = '#' * int(round(self._bar_step * self.current))
blank = ' ' * (self._bar_size - len(bar))
self.output.write(f"\r[{bar}{blank}] {self.current}")
Я включил блокировку потокапоскольку ваш пример кода импортирует threading
, я предполагаю, что вы захотите использовать его в такой среде.
Приведенный выше класс использует фиксированную ширину для индикатора выполнения и стирается записьюиз серии пробелов перед возвратом к крайнему левому столбцу с \r
.
Я также сделал полосу фиксированной ширины, чтобы она заполнялась слева направо, а не растянулась по экрану.
Затем убедитесь, что вы «печатаете» на этом объекте:
if __name__ == "__main__":
progress_bar = ProgressConsole(10)
print = progress_bar.print # replace built-in with our own version
print("Starting in main...")
progress_bar.increment()
print("\nOther print statement here.")
print("Nice day, expensive day.")
progress_bar.increment(2)
doThis()
progress_bar.increment()
doThat()
progress_bar.increment()
doThis()
doThat()
progress_bar.increment(2)
doThat()
doThat()
progress_bar.increment()
wrapUp()
progress_bar.increment(2)
Окончательный результат для вышеприведенного будет следующим:
Starting in main...
Other print statement here.
Nice day, expensive day.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing that.
Doing that.
Doing that.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing that.
Doing that.
Doing that.
Doing that.
Doing that.
Doing that.
Doing that.
Doing that.
Doing that.
Total found
[###########################################################################] 10
При вставке нескольких случайных снов он выглядитвот так при работе: