我知道可以用“\ r”一致地重写终端中显示的最后一行,但是我无法确定是否有办法返回并编辑控制台中打印的前一行。
我想要做的是重新打印基于文本的RPG的多行,但朋友也想知道这个应用程序有一行专用于进度条,另一行描述下载。
即。控制台将打印:
移动文件:NameOfFile.txt
总进度:[########] 40%
然后在程序运行时适当更新(到两行)。
答案 0 :(得分:40)
在Unix上,使用curses模块。
在Windows上,有几个选项:
使用curses的简单示例(我总是诅咒n00b):
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()
答案 1 :(得分:4)
最终,如果你想操纵屏幕,你需要使用底层的OS库,通常是:
如果您不介意坚持使用某个操作系统或者很乐意在Windows上安装第三方库,@ codeape的答案已经为您提供了许多选项。
但是,如果您想要一个只需pip install的跨平台解决方案,则可以使用asciimatics。作为开发此软件包的一部分,我必须解决环境之间的差异,以提供适用于Linux,OSX和Windows的单个API。
答案 2 :(得分:3)
这是一个Python 2/3的Python模块,可以用几行代码简单地解决这种情况; D
reprint - A simple module for Python 2/3 to print and refresh multi line output contents in terminal
您只需将output
个实例视为普通dict
或list
(取决于您使用的模式)。当您在output
实例中修改该内容时,终端中的输出将自动刷新:D
根据您的需要,这里是代码:
from reprint import output
import time
if __name__ == "__main__":
with output(output_type='dict') as output_lines:
for i in range(10):
output_lines['Moving file'] = "File_{}".format(i)
for progress in range(100):
output_lines['Total Progress'] = "[{done}{padding}] {percent}%".format(
done = "#" * int(progress/10),
padding = " " * (10 - int(progress/10)),
percent = progress
)
time.sleep(0.05)
答案 3 :(得分:0)
赞:
#!/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
我在用Go语言编写的Jiri项目中发现了这一点。
甚至更好:完成后擦除所有行:
#!/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
答案 4 :(得分:0)
回车符可以用于行首,而ANSI代码ESC A
("\033[A"
)可以使您上一行。这适用于Linux。通过使用colorama
包来启用ANSI代码,它可以在Windows上运行:
import time
import sys
import colorama
colorama.init()
print("Line 1")
time.sleep(1)
print("Line 2")
time.sleep(1)
print("Line 3 (no eol)", end="")
sys.stdout.flush()
time.sleep(1)
print("\rLine 3 the sequel")
time.sleep(1)
print("\033[ALine 3 the second sequel")
time.sleep(1)
print("\033[A\033[A\033[ALine 1 the sequel")
time.sleep(1)
print() # skip two lines so that lines 2 and 3 don't get overwritten by the next console prompt
print()
输出:
> python3 multiline.py
Line 1 the sequel
Line 2
Line 3 the second sequel
>
在后台,colorama可能使用SetConsoleMode
启用了Console Virtual Terminal Sequences
。
答案 5 :(得分:-1)
我找到了一个带有“ magic_char”的简单解决方案。
magic_char = '\033[F'
multi_line = 'First\nSecond\nThird'
ret_depth = magic_char * multi_line.count('\n')
print('{}{}'.format(ret_depth, multi_line), end='', flush = True)