输出到同一行覆盖以前的输出? python(2.5)
我正在写一个简单的ftp下载器。 部分代码是这样的:
ftp.retrbinary("RETR " + file_name, process)
我正在调用函数进程来处理callback:
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...
但我希望它打印这一行,下一次重印/刷新,所以它只会显示一次,我会看到下载的进度…
怎么办?
这是Python 3.x的代码:
print(os.path.getsize(file_name)/1024+'KB / '+size+' KB downloaded!', end='\r')
end=
关键字是这里的工作 – 默认情况下, print()
以换行符( \n
)结尾,但可以用不同的stringreplace。 在这种情况下,用回车结束该行而不是将光标返回到当前行的开始位置。 因此,不需要为这种简单的用法导入sys
模块。 print()
实际上有一些关键字参数 ,可以用来大大简化代码。
要在Python 2.6+上使用相同的代码,请在文件的顶部放置以下行:
from __future__ import print_function
如果您只想更改一行,请使用\r
。 \r
表示回车。 它的效果仅仅是把光标放回当前行的开头。 它不会消除任何东西。 同样, \b
可以用来向后转一个字符。 (有些terminal可能不支持所有这些function)
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)
看看curses模块文档和curses模块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()
这是我的小class,可以重印文字块。 它正确地清除了以前的文本,因此您可以用较短的新文本覆盖旧文本而不会造成混乱。
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解决scheme更短,但也更难以维护。
您可以在string的末尾添加“\ r”,并在打印function结束时加上一个逗号。 例如:
print(os.path.getsize(file_name)/1024+'KB / '+size+' KB downloaded!\r'),