Вывести на ту же строку, а не новую строку в Python - PullRequest
60 голосов
/ 06 августа 2010

По сути, я хочу сделать противоположное тому, что сделал этот парень ... хе-хе.

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

У меня есть программа, которая сообщает мне, как далеко она находится.

for i in some_list:
    #do a bunch of stuff.
    print i/len(some_list)*100," percent complete"

Так что если бы len (some_list) было 50, я напечатал бы последнюю строку 50 раз.Я хочу напечатать одну строку и продолжать обновлять эту строку.Я знаю, я знаю, что это, пожалуй, самый слабый вопрос, который вы будете читать весь день.Я просто не могу понять, какие четыре слова мне нужно вставить в Google, чтобы получить ответ.

Обновление!Я попробовал предложение mvds, которое казалось правильным.Новый код

print percent_complete,"           \r",

Процент завершения - это просто строка (я абстрагировался впервые, когда я пытался быть буквальным).В результате теперь он запускает программу, не печатает НИЧЕГО до тех пор, пока программа не будет завершена, а затем печатает «100% завершено» в одной и только одной строке.

Без возврата каретки (но сзапятая, половина предложения mvds) ничего не печатает до конца.А потом печатает:

0 percent complete     2 percent complete     3 percent complete     4 percent complete    

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

С возвратом каретки и без запятой она ведет себя точно так же, как ни с одной из них.

Ответы [ 10 ]

73 голосов
/ 06 августа 2010

Это называется возврат каретки, или \r

Используйте

print i/len(some_list)*100," percent complete         \r",

Запятая запрещает печати добавлять новую строку. (и пробелы сохранят строку свободной от предыдущего вывода)

Кроме того, не забудьте завершить с print "", чтобы получить хотя бы завершающий перевод строки!

27 голосов
/ 19 сентября 2011

Из python 3.x вы можете сделать:

print('bla bla', end='')

(который также можно использовать в Python 2.6 или 2.7, поставив from __future__ import print_function вверху вашего скрипта / модуля)

Пример строки состояния консоли Python:

import time

# status generator
def range_with_status(total):
    """ iterate from 0 to total and show progress in console """
    n=0
    while n<total:
        done = '#'*(n+1)
        todo = '-'*(total-n-1)
        s = '<{0}>'.format(done+todo)
        if not todo:
            s+='\n'        
        if n>0:
            s = '\r'+s
        print(s, end='')
        yield n
        n+=1

# example for use of status generator
for i in range_with_status(10):
    time.sleep(0.1)
19 голосов
/ 18 октября 2015

Для меня то, что сработало, было сочетанием ответов Реми и Сириусда:

from __future__ import print_function
import sys

print(str, end='\r')
sys.stdout.flush()
12 голосов
/ 25 марта 2013

для консоли вам, вероятно, понадобится

sys.stdout.flush()

для принудительного обновления.Я думаю, что использование , в печати заблокирует вывод stdout и как-то не обновится

4 голосов
/ 26 июня 2018

Никто не упомянул, что в Python 3.3+ вам не нужно sys.stdout.flush(). print('foobar', end='', flush=True) работает.

3 голосов
/ 06 августа 2010

Это работает для меня, взломал его один раз, чтобы увидеть, возможно ли это, но на самом деле никогда не использовал в моей программе (графический интерфейс намного лучше):

import time
f = '%4i %%'
len_to_clear = len(f)+1
clear = '\x08'* len_to_clear
print 'Progress in percent:'+' '*(len_to_clear),
for i in range(123):
    print clear+f % (i*100//123),
    time.sleep(0.4)
raw_input('\nDone')
2 голосов
/ 08 июня 2017
import time
import sys


def update_pct(w_str):
    w_str = str(w_str)
    sys.stdout.write("\b" * len(w_str))
    sys.stdout.write(" " * len(w_str))
    sys.stdout.write("\b" * len(w_str))
    sys.stdout.write(w_str)
    sys.stdout.flush()

for pct in range(0, 101):
    update_pct("{n}%".format(n=str(pct)))
    time.sleep(0.1)

\b переместит местоположение курсора назад на один пробел
Таким образом, мы переместим его назад до начала строки
Затем мы напишем пробелы, чтобы очистить текущую строку - какмы пишем пробелы, на которые курсор перемещается вперед / вправо на единицу
Итак, мы должны переместить курсор назад в начало строки, прежде чем записать наши новые данные

Протестировано на Windows cmd с использованием Python 2.7

1 голос
/ 06 августа 2010

Попробуйте так:

for i in some_list:
    #do a bunch of stuff.
    print i/len(some_list)*100," percent complete",

(с запятой в конце.)

0 голосов
/ 26 апреля 2019

Для Python 3.6+ и для любых list, а не просто int с, а также для использования всей ширины окна консоли и без перехода на новую строку, вы можете использовать следующее:

примечание: обратите внимание, что функция get_console_with() будет работать только в системах на базе Linux, и поэтому вам придется переписать ее для работы в Windows.

import os
import time

def get_console_width():
    """Returns the width of console.

    NOTE: The below implementation works only on Linux-based operating systems.
    If you wish to use it on another OS, please make sure to modify it appropriately.
    """
    return int(os.popen('stty size', 'r').read().split()[1])


def range_with_progress(list_of_elements):
    """Iterate through list with a progress bar shown in console."""

    # Get the total number of elements of the given list.
    total = len(list_of_elements)
    # Get the width of currently used console. Subtract 2 from the value for the
    # edge characters "[" and "]"
    max_width = get_console_width() - 2
    # Start iterating over the list.
    for index, element in enumerate(list_of_elements):
        # Compute how many characters should be printed as "done". It is simply
        # a percentage of work done multiplied by the width of the console. That
        # is: if we're on element 50 out of 100, that means we're 50% done, or
        # 0.5, and we should mark half of the entire console as "done".
        done = int(index / total * max_width)
        # Whatever is left, should be printed as "unfinished"
        remaining = max_width - done
        # Print to the console.
        print(f'[{done * "#"}{remaining * "."}]', end='\r')
        # yield the element to work with it
        yield element
    # Finally, print the full line. If you wish, you can also print whitespace
    # so that the progress bar disappears once you are done. In that case do not
    # forget to add the "end" parameter to print function.
    print(f'[{max_width * "#"}]')


if __name__ == '__main__':
    list_of_elements = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
    for e in range_with_progress(list_of_elements):
        time.sleep(0.2)

0 голосов
/ 14 июля 2017

На основе Ответ Реми для Python 2.7+ используйте это:

from __future__ import print_function
import time

# status generator
def range_with_status(total):
    """ iterate from 0 to total and show progress in console """
    import sys
    n = 0
    while n < total:
        done = '#' * (n + 1)
        todo = '-' * (total - n - 1)
        s = '<{0}>'.format(done + todo)
        if not todo:
            s += '\n'
        if n > 0:
            s = '\r' + s
        print(s, end='\r')
        sys.stdout.flush()
        yield n
        n += 1


# example for use of status generator
for i in range_with_status(50):
    time.sleep(0.2)
...