在控制台中重写多行
我知道可以用"\r"这个符号来不断地重写终端中显示的最后一行,但我在想有没有办法去修改之前打印的那些行。
我想做的是在一个基于文本的角色扮演游戏中重新打印多行内容,不过我的一个朋友也在问这个问题,他的应用程序有一行是用来显示进度条的,另一行则是描述下载情况。
比如,控制台会打印:
Moving file: NameOfFile.txt
Total Progress: [######## ] 40%
然后在程序运行时,适当地更新这两行内容。
7 个回答
8
总的来说,如果你想要控制屏幕显示,就需要使用操作系统底层的库,通常这些库包括:
- 在Linux或OSX上使用curses(或者是由terminfo/termcap数据库管理的终端控制代码)
- 在Windows上使用win32控制台API。
@codeape的回答已经给你提供了一些选项,如果你不介意只在一个操作系统上工作,或者愿意在Windows上安装第三方库。
不过,如果你想要一个跨平台的解决方案,并且可以简单地通过pip安装,你可以使用asciimatics。在开发这个包的过程中,我需要解决不同环境之间的差异,以提供一个在Linux、OSX和Windows上都能工作的统一API。
19
像这样:
#!/usr/bin/env python
import sys
import time
from collections import deque
queue = deque([], 3)
for t in range(20):
time.sleep(0.5)
s = "update %d" % t
for _ in range(len(queue)):
sys.stdout.write("\x1b[1A\x1b[2K") # move up cursor and delete whole line
queue.append(s)
for i in range(len(queue)):
sys.stdout.write(queue[i] + "\n") # reprint the lines
我在Jiri项目中发现了这个,这个项目是用Go语言写的。
更棒的是:完成后删除所有后面的行:
#!/usr/bin/env python
import sys
import time
from collections import deque
queue = deque([], 3)
t = 0
while True:
time.sleep(0.5)
if t <= 20:
s = "update %d" % t
t += 1
else:
s = None
for _ in range(len(queue)):
sys.stdout.write("\x1b[1A\x1b[2K") # move up cursor and delete whole line
if s != None:
queue.append(s)
else:
queue.popleft()
if len(queue) == 0:
break
for i in range(len(queue)):
sys.stdout.write(queue[i] + "\n") # reprint the lines
56
在Unix系统上,可以使用curses模块。
在Windows系统上,有几个选择:
- PDCurses: http://www.lfd.uci.edu/~gohlke/pythonlibs/
- 上面提到的HOWTO推荐使用Console模块
- http://newcenturycomputers.net/projects/wconio.html
- http://docs.activestate.com/activepython/2.6/pywin32/win32console.html
这是一个使用curses的简单例子(我对curses完全是小白):
import curses
import time
def report_progress(filename, progress):
"""progress: 0-10"""
stdscr.addstr(0, 0, "Moving file: {0}".format(filename))
stdscr.addstr(1, 0, "Total progress: [{1:10}] {0}%".format(progress * 10, "#" * progress))
stdscr.refresh()
if __name__ == "__main__":
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
try:
for i in range(10):
report_progress("file_{0}.txt".format(i), i+1)
time.sleep(0.5)
finally:
curses.echo()
curses.nocbreak()
curses.endwin()