Как мне записать вывод в том же месте на консоли?

158

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

вывод:

Загрузка файла FooFile.txt [47%]

Я пытаюсь избежать чего-то вроде этого:

     Downloading File FooFile.txt [47%]
     Downloading File FooFile.txt [48%]
     Downloading File FooFile.txt [49%]

Как мне это сделать?


Дубликат : Как я могу печатать поверх текущей строки в приложении командной строки?

scottm
источник
1
Вас может заинтересовать этот простой в использовании модуль, это текстовый индикатор выполнения. pypi.python.org/pypi/progressbar/2.2
wim

Ответы:

254

Вы также можете использовать возврат каретки:

sys.stdout.write("Download progress: %d%%   \r" % (progress) )
sys.stdout.flush()
codelogic
источник
13
Очень распространенное и простое решение. Примечание: если ваша линия длиннее, чем ширина вашего терминала, это будет ужасно.
ephemient
5
Мне также пришлось добавить вызов sys.stdout.flush (), чтобы курсор не подпрыгивал
scottm
19
Можно ли сделать это с несколькими строками? Допустим, у меня есть три разные загрузки, и я хочу показать прогресс каждой из них в отдельной строке.
EarlCrapstone
11
Я хотел бы поставить \rв начале строки, и добавить, \x1b[Kчтобы очистить предыдущий текст.
Авгурар
11
Кажется, что самое простое решение для Python 3 (как упомянуто в ответах ниже): print("sample text", end='\r", flush=True)
Cyrus
35

Python 2

Мне нравится следующее:

print 'Downloading File FooFile.txt [%d%%]\r'%i,

Демо-версия:

import time

for i in range(100):
    time.sleep(0.1)
    print 'Downloading File FooFile.txt [%d%%]\r'%i,

Python 3

print('Downloading File FooFile.txt [%d%%]\r'%i, end="")

Демо-версия:

import time

for i in range(100):
    time.sleep(0.1)
    print('Downloading File FooFile.txt [%d%%]\r'%i, end="")

Консоль отладчика PyCharm с Python 3

# On PyCharm Debugger console, \r needs to come before the text.
# Otherwise, the text may not appear at all, or appear inconsistently.
# tested on PyCharm 2019.3, Python 3.6

import time

print('Start.')
for i in range(100):
    time.sleep(0.02)
    print('\rDownloading File FooFile.txt [%d%%]'%i, end="")
print('\nDone.')
RSabet
источник
9
используйте это для python 3+: print ('Загрузка файла FooFile.txt [% d %%] \ r'% i, end = "")
hkoosha
На консоли PyCharm Debugger \ r должен находиться перед текстом. В противном случае текст может не отображаться вообще или отображаться непоследовательно. Я добавил версию, которая работает для меня как редактирование, потому что я не мог написать многострочный код в этом ответе. Я включил его в свою суть, чтобы люди могли просматривать его, пока редактирование ожидает одобрения: gist.github.com/yulkang/40168c7729a7a7b96d0116d8b1bc26df
Юл Кан
«\ r» в конце строки работает для меня в консоли отладчика PyCharm 2020.1 (PyCharm 2020.1.2 (Community Edition); сборка № PC-201.7846.77, построена 31 мая 2020 года).
батты
28

Используйте библиотеку обработки терминала, такую ​​как модуль curses :

Модуль curses предоставляет интерфейс для библиотеки curses, де-факто стандарта для портативной расширенной обработки терминала.

гимель
источник
1
Недоступно для Windows.
Диего Херранц
3
@Diego теперь в Windows есть библиотека поддержки модуля curses. см. stackoverflow.com/a/19851287/1426237
Plexico
15

Напечатайте символ возврата на обратную сторону \bнесколько раз, а затем перезапишите старый номер новым номером.

Зак Скривена
источник
интересно, я не думал делать это таким образом.
Крис Балланс
Мне это нравится, потому что он не очищает предыдущие команды (если у вас есть несколько этапов, которые вы хотите оставить на экране)
Натан Доннеллан
3
Использование возврата каретки (например print 'Downloading.... \r') также не удаляет предыдущие данные, но предотвращает необходимость знать, как далеко назад нужно выполнить резервное копирование.
cod3monk3y
8
#kinda like the one above but better :P

from __future__ import print_function
from time import sleep

for i in range(101):
  str1="Downloading File FooFile.txt [{}%]".format(i)
  back="\b"*len(str1)
  print(str1, end="")
  sleep(0.1)
  print(back, end="")
Кристиан Кальдерон
источник
Почему это лучше, чем выше (я Python n00b, поэтому, пожалуйста, извините мое невежество :-))?
BalinKingOfMoria восстанавливает CM
7

Для Python 3xx:

import time
for i in range(10):
    time.sleep(0.2) 
    print ("\r Loading... {}".format(i)+str(i), end="")
TheRutubeify
источник
4

Оптимальное решение, которое работает для меня:

from __future__ import print_function
import sys
for i in range(10**6):
    perc = float(i) / 10**6 * 100
    print(">>> Download is {}% complete      ".format(perc), end='\r')
    sys.stdout.flush()
print("")

Это sys.stdout.flushважно, иначе это становится действительно неуклюжим, и print("")выход из цикла for также важен.

ОБНОВЛЕНИЕ : Как уже упоминалось в комментариях, printтакже есть flushаргумент. Таким образом, следующее также будет работать:

from __future__ import print_function
for i in range(10**6):
    perc = float(i) / 10**6 * 100
    print(">>> Download is {}% complete      ".format(perc), end='\r', flush=True)
print("")
Майкл Холл
источник
1
В современном Python вы можете указывать аргумент flush=Trueto print, поэтому дополнительный sys.stdout.flush()вызов не требуется .
PM 2Ring
0
x="A Sting {}"
   for i in range(0,1000000):
y=list(x.format(i))
print(x.format(i),end="")

for j in range(0,len(y)):
    print("\b",end="")
Малайская хазарика
источник