Индикатор выполнения среди других операторов печати не работает - полезный индикатор выполнения не найден - PullRequest
0 голосов
/ 10 апреля 2019

Intro (Поездка на Межзвездном Офисном Кресле)

У меня есть программа, которая использует индикатор выполнения, чтобы показать конечному пользователю, работает программа или нет.Это должно сказать конечному пользователю, как долго ему ждать и работает ли программа.Этот вопрос возник после прочтения этого интересного потока переполнения стека: Текстовая строка прогресса в консоли

Проблемы / вызовы

Первая проблема - это прогрессВ настоящее время бар работает только в цикле и просто печатает числа в диапазоне.Это не полезно.Зачем кому-то нужна программа с индикатором выполнения, который просто показывает прогресс одного цикла, а не то, что делает остальная часть программы.

Вторая проблема заключается в том, что, когда у меня есть другие операторы печати с индикатором выполнения, внезапно в командную строку выводятся несколько индикаторов выполнения вместо одного индикатора выполнения, который появляется для анимации при каждом обновлении индикатора выполнения.

Как сделать так, чтобы индикатор выполнения всегда был внизу терминала, а другие операторы печати над ним?

Другая проблема заключается в использовании операционной системы Windows 7 (ОС).

Код

Пожалуйста, ознакомьтесь со следующим примером кода, который я имею для вас:

import sys
import time
import threading



def progress_bar(progress):
    sys.stdout.write('\r[{0}] {1}'.format('#' * int(progress/10 * 10), progress))


def doThis():
    for i in range(10):
        print("Doing this.")

def doThat():
    for i in range(3):
        print("Doing that.")

def wrapUp():
    total = 2+ 2
    print("Total found")
    return total


if __name__ == "__main__":

  print("Starting in main...")
  progress_bar(1)
  print("\nOther print statement here.")
  print("Nice day, expensive day.")
  progress_bar(3)

  doThis()
  progress_bar(4)
  doThat()
  progress_bar(5)
  doThis()
  doThat()
  progress_bar(6)
  progress_bar(7)
  doThat()
  doThat()
  progress_bar(8)
  wrapUp()
  progress_bar(9)
  progress_bar(10)

Что печатает программа

   Starting in main...
[#] 1
Other print statement here.
Nice day, expensive day.
[###] 3Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
Doing this.
[####] 4Doing that.
Doing that.
Doing that.
[#####] 5Doing 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.
[#######] 7Doing that.
Doing that.
Doing that.
Doing that.
Doing that.
Doing that.
[########] 8Total found
[##########] 10

1 Ответ

2 голосов
/ 11 апреля 2019

Вы должны сделать три вещи:

  • сохранить состояние индикатора выполнения в отдельном объекте, для которого вы можете вызывать методы для обновления состояния панели в разных циклах.
  • при печатииндикатор выполнения, убедитесь, что при выводе на консоль выводится новая строка
  • , сначала очистите текущую строку, а затем заново отрисуйте строку после печати. ​​

Вы покрываете первые два, несколько, но не третий.Вероятно, лучше всего инкапсулировать управление консолью в классе, который также управляет индикатором выполнения, чтобы он мог выполнять очистку, печать и повторное отображение всего в одном месте:

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

При вставке нескольких случайных снов он выглядитвот так при работе:

progressbar running

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...