Заменить вывод консоли в Python - PullRequest
79 голосов
/ 29 мая 2011

Мне интересно, как я мог бы создать один из этих изящных консольных счетчиков в Python, как в некоторых C / C ++ - программах.

У меня есть цикл, который делает вещи, и токовый вывод выглядит следующим образом:

Doing thing 0
Doing thing 1
Doing thing 2
...

что было бы лучше, так это обновление последней строки;

X things done.

Я видел это в ряде консольных программ, и мне интересно, смогу ли я сделать это в Python.

Ответы [ 8 ]

114 голосов
/ 29 мая 2011

Простое решение - просто написать "\r" перед строкой и не добавлять новую строку;если строка никогда не становится короче, этого достаточно ...

sys.stdout.write("\rDoing thing %i" % i)
sys.stdout.flush()

Чуть более изощренным является индикатор выполнения ... Я использую это:

def startProgress(title):
    global progress_x
    sys.stdout.write(title + ": [" + "-"*40 + "]" + chr(8)*41)
    sys.stdout.flush()
    progress_x = 0

def progress(x):
    global progress_x
    x = int(x * 40 // 100)
    sys.stdout.write("#" * (x - progress_x))
    sys.stdout.flush()
    progress_x = x

def endProgress():
    sys.stdout.write("#" * (40 - progress_x) + "]\n")
    sys.stdout.flush()

Вы звоните startProgress передать описание операции, затем progress(x), где x - это процент и, наконец, endProgress()

28 голосов
/ 04 июня 2016

Более элегантное решение может быть:

def progressBar(value, endvalue, bar_length=20):

        percent = float(value) / endvalue
        arrow = '-' * int(round(percent * bar_length)-1) + '>'
        spaces = ' ' * (bar_length - len(arrow))

        sys.stdout.write("\rPercent: [{0}] {1}%".format(arrow + spaces, int(round(percent * 100))))
        sys.stdout.flush()

вызовите эту функцию со значением и конечным значением, результат должен быть

Percent: [------------->      ] 69%
7 голосов
/ 09 января 2014

Для тех, кто наткнулся на это спустя годы (как и я), я немного подправил методы 6502, чтобы индикатор выполнения уменьшался, а также увеличивался.Полезно в немного большем количестве случаев.Спасибо 6502 за отличный инструмент!

По сути, единственное отличие состоит в том, что вся строка #s и -s записывается при каждом вызове progress (x), и курсор всегда возвращается в началобар.

def startprogress(title):
    """Creates a progress bar 40 chars long on the console
    and moves cursor back to beginning with BS character"""
    global progress_x
    sys.stdout.write(title + ": [" + "-" * 40 + "]" + chr(8) * 41)
    sys.stdout.flush()
    progress_x = 0


def progress(x):
    """Sets progress bar to a certain percentage x.
    Progress is given as whole percentage, i.e. 50% done
    is given by x = 50"""
    global progress_x
    x = int(x * 40 // 100)                      
    sys.stdout.write("#" * x + "-" * (40 - x) + "]" + chr(8) * 41)
    sys.stdout.flush()
    progress_x = x


def endprogress():
    """End of progress bar;
    Write full bar, then move to next line"""
    sys.stdout.write("#" * 40 + "]\n")
    sys.stdout.flush()
7 голосов
/ 29 мая 2011

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

def progress(x):
    out = '%s things done' % x  # The output
    bs = '\b' * 1000            # The backspace
    print bs,
    print out,

Затем я вызвал его в цикле в моей основной функции следующим образом:

def main():
    for x in range(20):
        progress(x)
    return

Это, конечно, сотрет всю строку, но вы можете возиться с ней, чтобы делать именно то, что вы хотите. Я закончил тем, что сделал индикатор выполнения, используя этот метод.

6 голосов
/ 29 мая 2011

Если я правильно понял (не уверен), что вы хотите печатать, используя <CR>, а не <LR>?

Если это так, то это возможно, пока консольный терминал позволяет это (он сломается при выводеsi перенаправлен в файл).

from __future__ import print_function
print("count x\r", file=sys.stdout, end=" ")
4 голосов
/ 06 марта 2019

Это можно сделать без использования библиотеки sys, если мы посмотрим на функцию print()

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

Вот мой код:

def update(n):
    for i in range(n):
        print("i:",i,sep='',end="\r",flush=True)
        #time.sleep(1)
3 голосов
/ 24 августа 2018

Добавлен немного больше функциональности к примеру Aravind Voggu :

def progressBar(name, value, endvalue, bar_length = 50, width = 20):

        percent = float(value) / endvalue

        arrow = '-' * int(round(percent*bar_length) - 1) + '>'

        spaces = ' ' * (bar_length - len(arrow))

        sys.stdout.write("\r{0: <{1}} : [{2}]{3}%".format(\
                         name, width, arrow + spaces, int(round(percent*100))))

        sys.stdout.flush()

        if value == endvalue:        

             sys.stdout.write('\n\n')

Теперь вы можете генерировать несколько индикаторов, не заменяя ранее.
Я также добавил имя в качестве значения с фиксированной шириной.

Для двух циклов и двухкратного использования progressBar () результат будет выглядеть так:


enter image description here

2 голосов
/ 14 июля 2018

В Python 3 вы можете сделать это для печати в одной строке:

print('', end='\r')

Особенно полезно для отслеживания последних обновлений и прогресса.

Я бы также порекомендовал tqdm отсюда , если кто-то хочет увидеть ход цикла.Он печатает текущую итерацию и итоговые итерации в виде строки прогресса с ожидаемым временем окончания.Супер полезно и быстро.Работает для python2 и python3.

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