Если бы у меня был следующий код:
for x in range(10):
print x
Я бы получил результат
1
2
etc..
Я хотел бы вместо печати новой строки заменить предыдущее значение и перезаписать его новым значением в той же строке.
Если бы у меня был следующий код:
for x in range(10):
print x
Я бы получил результат
1
2
etc..
Я хотел бы вместо печати новой строки заменить предыдущее значение и перезаписать его новым значением в той же строке.
Ответы:
Один из способов - использовать '\r'символ возврата каретки ( ) для возврата в начало строки без перехода к следующей строке:
for x in range(10):
print '{0}\r'.format(x),
print
Запятая в конце оператора печати говорит ему не переходить к следующей строке. Последний оператор печати переходит к следующей строке, поэтому ваше приглашение не перезапишет окончательный результат.
Теперь, когда Python 2 является EOL, ответ Python 3 имеет больше смысла. Для Python 3.5 и ранее:
for x in range(10):
print('{}\r'.format(x), end="")
print()
В Python 3.6 и новее f-строки читаются лучше:
for x in range(10):
print(f'{x}\r', end="")
print()
%оператор является устаревшим. По сути, все строки теперь имеют метод форматирования . В данном случае это {0}означает «первый аргумент для format()» (отсчет начинается с 0).
re.sub(r'\$<\d+>[/*]?', '', curses.tigetstr('el') or '')вы получите правильную строку от стирания до конца строки для любого терминала, который есть у пользователя. Не забудьте инициализировать cursesчто-то вроде curses.setupterm(fd=sys.stdout.fileno()), и используйте, sys.stdout.isatty()чтобы убедиться, что ваш вывод не перенаправляется в файл. См. Code.activestate.com/recipes/475116 для получения полного модуля Python с управлением курсором и поддержкой цвета.
import curses; curses.setupterm(fd=sys.stdout.fileno()); print(hex(curses.tigetstr('cr')));он должен напечатать шестнадцатеричные коды последовательности символов, чтобы перейти в начало строки.
Поскольку я оказался здесь через Google, но использую Python 3, вот как это будет работать в Python 3:
for x in range(10):
print("Progress {:2.1%}".format(x / 10), end="\r")
Связанный ответ здесь: Как я могу подавить новую строку после оператора печати?
testingи ваш второй цикл печати, testрезультат после второго прохода все равно будет testing- теперь я вижу, что @ Nagasaki45 указал на это
print("\r", message, end="")
Ответ @Mike DeSimone, вероятно, будет работать большую часть времени. Но...
for x in ['abc', 1]:
print '{}\r'.format(x),
-> 1bc
Это потому, что '\r' единственный возвращается к началу строки, но не очищает вывод.
Если вам достаточно поддержки POSIX, следующая строка очистит текущую строку и оставит курсор в ее начале:
print '\x1b[2K\r',
Он использует escape-код ANSI для очистки строки терминала. Более подробную информацию можно найти в Википедии и в этом замечательном выступлении. .
Найденное (не очень хорошее) решение выглядит так:
last_x = ''
for x in ['abc', 1]:
print ' ' * len(str(last_x)) + '\r',
print '{}\r'.format(x),
last_x = x
-> 1
Одним из преимуществ является то, что он будет работать и с окнами.
Перед посещением этой ветки у меня был такой же вопрос. Для меня sys.stdout.write работал, только если я правильно очищаю буфер, т.е.
for x in range(10):
sys.stdout.write('\r'+str(x))
sys.stdout.flush()
Без промывки результат печатается только в конце скрипта
stringvar.ljust(10,' ')в случае строк переменной длины.
Подавить новую строку и напечатать \r.
print 1,
print '\r2'
или напишите в stdout:
sys.stdout.write('1')
sys.stdout.write('\r2')
Попробуй это:
import time
while True:
print("Hi ", end="\r")
time.sleep(1)
print("Bob", end="\r")
time.sleep(1)
У меня это сработало. end="\r"Часть делает его перезаписать предыдущую строку.
ПРЕДУПРЕЖДЕНИЕ!
Если вы распечатываете hi, а затем распечатываете с helloиспользованием \r, вы получите, hilloпотому что результат написан поверх двух предыдущих букв. Если вы распечатываете hiс пробелами (которые здесь не отображаются), он будет выводиться hi. Чтобы исправить это, распечатайте пробелы, используя \r.
Hi BobHi BobHi BobHi BobHi Bob. Python 3.7.1
\r- это начало, а не конец.
Мне не удалось заставить ни одно из решений на этой странице работать для IPython , но небольшая вариация решения @Mike-Desimone сработала: вместо завершения строки с помощью возврата каретки начните строку с возврата каретки:
for x in range(10):
print '\r{0}'.format(x),
Кроме того, этот подход не требует второго оператора печати.
for x in range(10):
time.sleep(0.5) # shows how its working
print("\r {}".format(x), end="")
time.sleep (0.5) показывает, как стирается предыдущий вывод, а новый вывод печатается "\ r", когда он находится в начале сообщения печати, он стирает предыдущий вывод перед новым выводом.
Это работает в Windows и Python 3.6.
import time
for x in range(10):
time.sleep(0.5)
print(str(x)+'\r',end='')
Принятый ответ не идеален . Строка, которая была напечатана первой, останется там, и если ваша вторая печать не покроет всю новую строку, вы получите мусорный текст.
Чтобы проиллюстрировать проблему, сохраните этот код как скрипт и запустите его (или просто посмотрите):
import time
n = 100
for i in range(100):
for j in range(100):
print("Progress {:2.1%}".format(j / 100), end="\r")
time.sleep(0.01)
print("Progress {:2.1%}".format(i / 100))
Результат будет выглядеть примерно так:
Progress 0.0%%
Progress 1.0%%
Progress 2.0%%
Progress 3.0%%
Что мне подходит, так это очистить линию перед тем, как оставить постоянную печать. Не стесняйтесь приспосабливаться к вашей конкретной проблеме:
import time
ERASE_LINE = '\x1b[2K' # erase line command
n = 100
for i in range(100):
for j in range(100):
print("Progress {:2.1%}".format(j / 100), end="\r")
time.sleep(0.01)
print(ERASE_LINE + "Progress {:2.1%}".format(i / 100)) # clear the line first
И теперь он печатает, как ожидалось:
Progress 0.0%
Progress 1.0%
Progress 2.0%
Progress 3.0%
Вот более чистая, более "подключаемая" версия ответа @ Nagasaki45. В отличие от многих других ответов здесь, он правильно работает со строками разной длины. Это достигается за счет очистки строки таким же количеством пробелов, как длина последней напечатанной строки. Также будет работать в Windows.
def print_statusline(msg: str):
last_msg_length = len(print_statusline.last_msg) if hasattr(print_statusline, 'last_msg') else 0
print(' ' * last_msg_length, end='\r')
print(msg, end='\r')
sys.stdout.flush() # Some say they needed this, I didn't.
print_statusline.last_msg = msg
Просто используйте это так:
for msg in ["Initializing...", "Initialization successful!"]:
print_statusline(msg)
time.sleep(1)
Этот небольшой тест показывает, что строки очищаются правильно даже для разной длины:
for i in range(9, 0, -1):
print_statusline("{}".format(i) * i)
time.sleep(0.5)
Я немного удивлен, что никто не использует символ возврата. Вот тот, который его использует.
import sys
import time
secs = 1000
while True:
time.sleep(1) #wait for a full second to pass before assigning a second
secs += 1 #acknowledge a second has passed
sys.stdout.write(str(secs))
for i in range(len(str(secs))):
sys.stdout.write('\b')
sys.stdout.flush()
(Python3) Это то, что у меня сработало. Если вы просто используете \ 010, он оставит символы, поэтому я немного изменил его, чтобы убедиться, что он перезаписывает то, что там было. Это также позволяет вам иметь что-то перед первым элементом печати и удалять только длину элемента.
print("Here are some strings: ", end="")
items = ["abcd", "abcdef", "defqrs", "lmnop", "xyz"]
for item in items:
print(item, end="")
for i in range(len(item)): # only moving back the length of the item
print("\010 \010", end="") # the trick!
time.sleep(0.2) # so you can see what it's doing
Еще один ответ, основанный на предыдущих ответах.
Содержимое pbar.py: import sys, shutil, datetime
last_line_is_progress_bar=False
def print2(print_string):
global last_line_is_progress_bar
if last_line_is_progress_bar:
_delete_last_line()
last_line_is_progress_bar=False
print(print_string)
def _delete_last_line():
sys.stdout.write('\b\b\r')
sys.stdout.write(' '*shutil.get_terminal_size((80, 20)).columns)
sys.stdout.write('\b\r')
sys.stdout.flush()
def update_progress_bar(current, total):
global last_line_is_progress_bar
last_line_is_progress_bar=True
completed_percentage = round(current / (total / 100))
current_time=datetime.datetime.now().strftime('%m/%d/%Y-%H:%M:%S')
overhead_length = len(current_time+str(current))+13
console_width = shutil.get_terminal_size((80, 20)).columns - overhead_length
completed_width = round(console_width * completed_percentage / 100)
not_completed_width = console_width - completed_width
sys.stdout.write('\b\b\r')
sys.stdout.write('{}> [{}{}] {} - {}% '.format(current_time, '#'*completed_width, '-'*not_completed_width, current,
completed_percentage),)
sys.stdout.flush()
Использование скрипта:
import time
from pbar import update_progress_bar, print2
update_progress_bar(45,200)
time.sleep(1)
update_progress_bar(70,200)
time.sleep(1)
update_progress_bar(100,200)
time.sleep(1)
update_progress_bar(130,200)
time.sleep(1)
print2('some text that will re-place current progress bar')
time.sleep(1)
update_progress_bar(111,200)
time.sleep(1)
print('\n') # without \n next line will be attached to the end of the progress bar
print('built in print function that will push progress bar one line up')
time.sleep(1)
update_progress_bar(111,200)
time.sleep(1)
Вот мое решение! Windows 10, Python 3.7.1
Я не уверен, почему этот код работает, но он полностью стирает исходную строку. Я собрал его из предыдущих ответов. Другие ответы просто вернули бы строку в начало, но если бы у вас была более короткая строка, она бы выглядела испорченной, как helloпревращается в byelo.
import sys
#include ctypes if you're on Windows
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
#end ctypes
def clearline(msg):
CURSOR_UP_ONE = '\033[K'
ERASE_LINE = '\x1b[2K'
sys.stdout.write(CURSOR_UP_ONE)
sys.stdout.write(ERASE_LINE+'\r')
print(msg, end='\r')
#example
ig_usernames = ['beyonce','selenagomez']
for name in ig_usernames:
clearline("SCRAPING COMPLETE: "+ name)
Вывод - каждая строка будет переписана без какого-либо старого текста, показывающего:
SCRAPING COMPLETE: selenagomez
Следующая строка (полностью переписана на той же строке):
SCRAPING COMPLETE: beyonce
Лучше перезаписать всю строку, иначе новая строка будет смешиваться со старыми, если новая строка будет короче.
import time, os
for s in ['overwrite!', 'the!', 'whole!', 'line!']:
print(s.ljust(os.get_terminal_size().columns - 1), end="\r")
time.sleep(1)
Пришлось использовать columns - 1в Windows.