如何在同一行覆盖之前的输出?

168 投票
13 回答
263065 浏览
提问于 2025-04-16 11:13

我正在写一个FTP下载器。代码的一部分大概是这样的:

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

我调用了一个叫做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...   

但是我希望它能打印这一行,然后下次再打印/刷新它,这样就只会显示一次,我就能看到下载的进度。

这该怎么做呢?

13 个回答

18

你可以看看这个 curses模块的文档 和这个 curses模块的使用指南

这里有一个非常简单的例子:

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()
47

如果你只想改变一行的内容,可以使用 \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)
308

这是适用于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

撰写回答