web-dev-qa-db-ja.com

コンソールで複数行を書き換える

ターミナルに表示される最後の行を常に「\ r」で書き換えることは可能ですが、コンソールに出力された前の行に戻って編集する方法があるかどうか、わかりません。

私がやりたいのは、テキストベースのRPGの複数の行を再印刷することですが、友人も、プログレスバー専用の1行とダウンロードを説明する別の行があるアプリケーションについてこれについて疑問に思っていました。

つまり、コンソールは次のように出力します。

Moving file: NameOfFile.txt  
Total Progress: [########              ] 40%

次に、プログラムの実行中に(両方の行に)適切に更新します。

35
JRJurman

Unixでは、 curses モジュールを使用します。

Windowsには、いくつかのオプションがあります。

Cursesを使用した簡単な例(私は合計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()
44
codeape

最終的には、画面を操作したい場合は、基本となるOSライブラリを使用する必要があります。

  • linuxまたはOSX上のcurses(または、terminfo/termcapデータベースによって追跡される基になる端末制御コード)
  • windows上のwin32コンソールAPI。

@codeapeからの回答は、1つのOSに固執することを気にしない場合、またはWindowsにサードパーティのライブラリをインストールすることに満足している場合、すでに多くのオプションのいくつかを提供しています。

ただし、単純にpipインストールできるクロスプラットフォームソリューションが必要な場合は、 asciimatics を使用できます。このパッケージの開発の一環として、Linux、OSX、およびWindowsで動作する単一のAPIを提供するために、環境間の違いを解決する必要がありました。

プログレスバーの場合、 このデモこのコード のように、BarChartオブジェクトを使用できます。

4
Peter Brittain

ここにPython両方のモジュールPython 2/3です)、これは数行のコードでそのような状況を簡単に解決できます; D

reprint-Python 2/3でターミナルの複数行の出力内容を印刷および更新するための単純なモジュール

その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
Yinzo

このような:

#!/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
0
Leedehai