Как я могу перезаписать / распечатать текущую строку в командной строке Windows?

В Unix я могу использовать \r (возврат каретки) или \b (backspace) для перезаписи текущей строки (печать поверх текста, который уже виден) в оболочке.

Могу ли я добиться того же эффекта в командной строке Windows из скрипта Python?

Я попробовал модуль curses, но, похоже, он недоступен в Windows.

Мой вопрос об индикаторе прогресса загрузки Python может быть полезным.

cschol 21.01.2009 16:55
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
24
1
48 947
10

Ответы 10

да:

import sys
import time

def restart_line():
    sys.stdout.write('\r')
    sys.stdout.flush()

sys.stdout.write('some data')
sys.stdout.flush()
time.sleep(2) # wait 2 seconds...
restart_line()
sys.stdout.write('other different data')
sys.stdout.flush()

Если вторые данные короче первых, символы первых данных остаются на консоли.

Hilal 09.08.2016 15:19

Простой способ, если вы просто хотите обновить предыдущую строку:

import time
for i in range(20):
    print str(i) + '\r',
    time.sleep(1)

В Windows (python 3) это, похоже, работает (без прямого использования stdout):

import sys

for i in reversed(range(0,20)):
  time.sleep(0.1)
  if (i == 19):
    print(str(i), end='', file=sys.stdout)
  else:
    print("\r{0:{width}".format(str(i), width = w, fill = ' ', align = 'right'), end='', file=sys.stdout)
  sys.stdout.flush()
  w = len(str(i))

Эта же строка обновляется каждый раз при вызове функции печати.

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

Это не сработает, поскольку вы определяете w после его вызова.

Aidan H 03.06.2019 06:02
import sys 
import time

for i in range(10):
    print '\r',         # print is Ok, and comma is needed.
    time.sleep(0.3)
    print i,
    sys.stdout.flush()  # flush is needed.

А если на IPython-ноутбуке, то вот так:

import time
from IPython.display import clear_output

for i in range(10):
    time.sleep(0.25)
    print(i)
    clear_output(wait=True)

http://nbviewer.ipython.org/github/ipython/ipython/blob/master/examples/notebooks/Animations%20Using%20clear_output.ipynb

ipython notebook / jupyter - это то, что я искал!

dmeu 13.08.2015 17:28

Я знаю, что это старый, но я хотел сказать свою версию (она работает на моем ПК в cmd, но не в режиме ожидания), чтобы переопределить строку в Python 3:

>>> from time import sleep
>>> for i in range(400):
>>>     print("\r" + str(i), end = "")
>>>     sleep(0.5)

Обновлено: Работает в Windows и Ubuntu.

Считайте Mac OS в

eggmatters 31.07.2020 20:48

По-прежнему нет решения для IDLE?

PouJa 12.11.2020 22:29

Просто у меня была эта проблема. Вы по-прежнему можете использовать \r даже в командной строке Windows, однако это вернет вас только к предыдущему разрыву строки (\n).

Если вы сделаете что-то вроде этого:

cnt = 0
print str(cnt)
while True:
    cnt += 1
    print "\r" + str(cnt)

Ты получишь:

0
1
2
3
4
5
...

Это потому, что \r возвращается только к последней строке. Поскольку вы уже написали символ новой строки с последним оператором печати, ваш курсор перемещается от начала новой пустой строки к началу той же новой пустой строки.

Чтобы проиллюстрировать, после того, как вы напечатаете первый 0, ваш курсор будет здесь:

0
| # <-- Cursor

Когда вы \r, вы переходите в начало строки. Но вы уже в начале очереди.

Исправление состоит в том, чтобы избежать печати символа \n, чтобы ваш курсор находился в той же строке, и \r правильно перезаписывал текст. Вы можете сделать это с помощью print 'text',. Запятая предотвращает печать символа новой строки.

cnt = 0
print str(cnt),
while True:
    cnt += 1
    print "\r" + str(cnt),

Теперь он правильно перезапишет строки.

Обратите внимание, что это Python 2.7, отсюда и операторы print.

Избегание новой строки точно устранило мою проблему, спасибо! В качестве дополнения в Python 3 можно использовать print(msg, end=' '), чтобы избежать новой строки.

Thomas Lang 14.05.2020 10:15

легкий способ :)

import sys
from time import sleep
import os

#print("\033[y coordinate;[x coordinateH Hello")
os.system('cls')
sleep(0.2)
print("\033[1;1H[]")
sleep(0.2)
print("\033[1;1H  []")
sleep(0.2)
print("\033[1;1H    []")
sleep(0.2)
print("\033[1;1H      []")
sleep(0.2)
print("\033[1;1H        []")
sleep(0.2)
print("\033[1;1H      []")
sleep(0.2)
print("\033[1;1H    []")
sleep(0.2)
print("\033[1;1H  []")
sleep(0.2)
print("\033[1;1H[]")
sleep(0.2)

Спасибо за все полезные ответы, ребята. Мне это было нужно :)

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

Вот что помогло мне, надеюсь, кому-то это пригодится:

import sys

def replace_cmd_line(output):
    """Replace the last command line output with the given output."""
    sys.stdout.write(output)
    sys.stdout.flush()
    sys.stdout.write('\r')
    sys.stdout.flush()

Вам нужен только один flush () в конце. Я не уверен, что sys.stdout.write(output + '\r') будет намного быстрее, чем вызовы двух методов (из-за выделения памяти для строки, копирования, GC), поэтому, вероятно, держать их отдельно друг от друга.

Aaron Digulla 25.01.2017 12:47

Самый простой способ - использовать два \ r - один в начале и один в конце

for i in range(10000):
    print('\r'+str(round(i*100/10000))+'%  Complete\r'),

Это пойдет довольно быстро

: - / Первый \r будет обработан 9999 раз зря. Если вы не знаете, где находится ваш курсор, вы можете вызвать print('\r')однажды перед циклом.

Aaron Digulla 04.09.2017 12:56

Да, этот вопрос задавали 11 лет назад, но это круто. Люблю импровизировать. Дополнение к ответу носкло:

import sys
import time

def restart_line():
    sys.stdout.write("\r")
    sys.stdout.flush()

string_one = "some data that is very long..."
sys.stdout.write(string_one)
sys.stdout.flush()

time.sleep(2)
restart_line()

string_two = "shorter data"
if len(string_two) < len(string_one):
    string_two = string_two+(" "*int((len(string_one)-len(string_two))))
    # This will overwrite the characters that would be left on the console

sys.stdout.write(string_two)
sys.stdout.flush()

Другие вопросы по теме