вывод в ту же строку, перезаписывая предыдущий вывод? на Python (2.5)

Я пишу простой FTP-загрузчик. Частью кода является что-то вроде этого:

ftp.retrbinary("RETR " + file_name, process)

Я вызываю процесс функции для обработки обратного вызова:

def process(data):
    print os.path.getsize(file_name)/1024, 'KB / ', size, 'KB downloaded!'
    file.write(data)

и вывод примерно такой:

1784  KB / KB 1829 downloaded!
1788  KB / KB 1829 downloaded!
etc...   

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

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

6 ответов


вот код для Python 3.x:

print(os.path.getsize(file_name)/1024+'KB / '+size+' KB downloaded!', end='\r')

на end= ключевое слово-это то, что здесь работает -- по умолчанию,print() завершается символом перевода строки (\n) символ, но его можно заменить другой строкой. В этом случае завершение строки возвращением каретки возвращает курсор к началу текущей строки. Таким образом, нет необходимости импортировать sys модуль для такого простого использования. print() фактически ряд аргументов ключевых слов который может быть использован для упрощения кода.

чтобы использовать тот же код на Python 2.6+, поместите следующую строку в верхней части файла:

from __future__ import print_function

если все вы хотите сделать, это изменить одну строку, используйте \r. \r означает возврат каретки. Его эффект заключается исключительно в том, чтобы вернуть каретку в начало текущей строки. Он ничего не стирает. Аналогично,\b может использоваться для перехода на один символ назад. (некоторые терминалы могут не поддерживать все эти функции)

import sys

def process(data):
    size_str = os.path.getsize(file_name)/1024, 'KB / ', size, 'KB downloaded!'
    sys.stdout.write('%s\r' % size_str)
    sys.stdout.flush()
    file.write(data)

посмотреть ругательства документации и модуль проклятий HOWTO.

очень простой пример:

import time
import curses

stdscr = curses.initscr()

stdscr.addstr(0, 0, "Hello")
stdscr.refresh()

time.sleep(1)

stdscr.addstr(0, 0, "World! (with curses)")
stdscr.refresh()

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

import re, sys

class Reprinter:
    def __init__(self):
        self.text = ''

    def moveup(self, lines):
        for _ in range(lines):
            sys.stdout.write("\x1b[A")

    def reprint(self, text):
        # Clear previous text by overwritig non-spaces with spaces
        self.moveup(self.text.count("\n"))
        sys.stdout.write(re.sub(r"[^\s]", " ", self.text))

        # Print new text
        lines = min(self.text.count("\n"), text.count("\n"))
        self.moveup(lines)
        sys.stdout.write(text)
        self.text = text

reprinter = Reprinter()

reprinter.reprint("Foobar\nBazbar")
reprinter.reprint("Foo\nbar")

я обнаружил, что для простого оператора печати в python 2.7 просто поставьте запятую в конце после вашего '\r'.

print os.path.getsize(file_name)/1024, 'KB / ', size, 'KB downloaded!\r',

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


вы можете просто добавить '\r ' в конце строки плюс запятую в конце функции печати. Например:

print(os.path.getsize(file_name)/1024+'KB / '+size+' KB downloaded!\r'),