Python - 在控制台中重写多行

时间:2011-07-27 06:47:06

标签: python printing console rewrite

我知道可以用“\ r”一致地重写终端中显示的最后一行,但是我无法确定是否有办法返回并编辑控制台中打印的前一行。

我想要做的是重新打印基于文本的RPG的多行,但朋友也想知道这个应用程序有一行专用于进度条,另一行描述下载。

即。控制台将打印:

移动文件:NameOfFile.txt
总进度:[########] 40%

然后在程序运行时适当更新(到两行)。

6 个答案:

答案 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库,通常是:

  • 在Linux或OSX上的curses(或由terminfo / termcap数据库跟踪的基础终端控制代码)
  • Windows上的win32控制台API。

如果您不介意坚持使用某个操作系统或者很乐意在Windows上安装第三方库,@ codeape的答案已经为您提供了许多选项。

但是,如果您想要一个只需pip install的跨平台解决方案,则可以使用asciimatics。作为开发此软件包的一部分,我必须解决环境之间的差异,以提供适用于Linux,OSX和Windows的单个API。

对于进度条,您可以使用this demo使用this code中显示的BarChart对象。

答案 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个实例视为普通dictlist(取决于您使用的模式)。当您在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

(也在此处发布:https://stackoverflow.com/a/64360937/461834

答案 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)
相关问题