Python - 在控制台中重写多行

JRJ*_*man 33 python printing console rewrite

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

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

即控制台将打印:

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

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

cod*_*ape 42

在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()
Run Code Online (Sandbox Code Playgroud)

  • 实际上有一个模块可以完成您想要的操作:[progressbar][http://code.google.com/p/python-progressbar/] (2认同)

小智 8

这是一个适用于 Python 2/3 的 Python 模块,它可以用几行代码简单地解决这种情况;D

reprint - Python 2/3 的简单模块,用于在终端中打印和刷新多行输出内容

您可以简单地将该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)
Run Code Online (Sandbox Code Playgroud)


Pet*_*ain 6

最终,如果您想操作屏幕,您需要使用底层操作系统库,它们通常是:

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

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

但是,如果您想要一个可以简单地 pip 安装的跨平台解决方案,您可以使用asciimatics。作为开发这个包的一部分,我不得不解决环境之间的差异,以提供一个适用于 Linux、OSX 和 Windows 的单一 API。

对于进度条,您可以使用此代码使用演示中所示的 BarChart 对象。


jtp*_*yda 6

回车符可用于转到行首,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()
Run Code Online (Sandbox Code Playgroud)

输出:

> python3 multiline.py
Line 1 the sequel
Line 2
Line 3 the second sequel
>
Run Code Online (Sandbox Code Playgroud)

在幕后,colorama 大概可以 使用SetConsoleMode.

(也发布在这里:https ://stackoverflow.com/a/64360937/461834 )


Lee*_*hai 5

像这样:

#!/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
Run Code Online (Sandbox Code Playgroud)

我在用 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
Run Code Online (Sandbox Code Playgroud)