3

Wget は速度情報を非常に明確な方法で stdout に出力します。ファイルのダウンロード中に速度が表示および更新され、バーが画面上をスクロールします。この種の出力を Python プログラムで複製したいと思います。これはどのように可能ですか?

cursesライブラリでこれができるはずだと思いました。これは私が思いついたものです:-

import curses, time

class Speeder( object ):
    """Show and refresh time and download speed in a curses interface."""
    t1 = 0. # start time
    t  = 0. # current time
    tf = 0. # end time
    def start(self, filename=None ):
        """Start timer"""
        self.t1 = self.t = time.time()
        curses.use_env(True)
        curses.initscr()
        self.win = curses.newwin(4, 0)
        if filename is not None:
            self.win.addnstr(filename, 50 )
            self.win.refresh()

    def update(self, rbytes):
        """Refresh speed."""
        t = time.time()
        td = t - self.t
        self.t = t
        speed = rbytes / td 
        self.win.addstr(0,54,str('{0:.02f} B/s'.format(speed)))
        self.win.refresh()

    def end(self):
        """End timer"""
        self.tf = time.time() 
        curses.endwin()


try:
    speed = Speeder()
    speed.start(filename='foo.bar')
    for i in xrange(10):
        time.sleep(0.5)
        speed.update(200)
finally:
    speed.end()

問題は、それがウィンドウ全体を占有することであり、実際には一度に 1 行しか必要ありません。すべてのコマンド ライン履歴をターミナル ウィンドウの上に押し戻すのは避けたいと思います。私が間違っている場合は修正してください。ただし、現在のところ、curses アプリは常にターミナル ウィンドウ全体を占有していると思います。

そこで、ttyおよびtermiosモジュールを調べましたが、やりたいことを実行している例が見つかりません。

最後に、いくつかの特殊文字をsys.stdoutに書き込むだけでそれを行うブログ投稿に出くわしました。私のSpeederクラスに彼のコードを適用して、私はこれを思いつきました:-

import sys
class Speeder( object ):
    """Show and refresh time and download speed."""
    t1 = 0. # start time
    t  = 0. # current time
    tf = 0. # end time
    def start(self, filename=None ):
        """Start timer"""
        self.t1 = self.t = time.time()
        if filename is not None:
            sys.stdout.write( '\r\x1b[K' + filename.ljust(50) )
            sys.stdout.flush()

    def update(self, rbytes):
        """Refresh speed."""
        t = time.time()
        td = t - self.t
        self.t = t
        speed = '{0} B/s'.format( rbytes / td )
        sys.stdout.write( "\r\x1b[K" + speed.rjust(65) )
        sys.stdout.flush()

    def end(self):
        """End timer"""
        self.tf = time.time()
        sys.stdout.write('\n')

これはコードの行数が少ないので気に入っていますが、何が起こっているのか、または curses.addstr 関数と同様に、行の一部のみを更新するように変更する方法がわからないのです。現在、ファイル名は空白で上書きされています。もちろん、Python から毎回行全体を構築するようにクラスを変更することもできますが、自分のニーズに合わせて調整するために、これを理解したいと思います。

著者は、これは VT100 端末でのみ可能であると述べています。それで、これはUnix端末でのみ機能すると思いますか?それは問題ありませんが、これが動作しない Unix 端末はありますか?

主題に関するより良いドキュメント、またはより複雑な例 (たとえば、複数行の更新、複数行の 1 行の更新、または行内の単一文字の更新など) はありますか? これは Python の機能のようには見えませんが、tty の機能のようです。そのため、何も見つけられなかったと思います。マニュアルページまたは読むべきものはありますか?

4

2 に答える 2

4

上記のコードはANSIエスケープコードを使用しています:https://en.wikipedia.org/wiki/ANSI_escape_code。見つけたコードを調べようとするときに探しているドキュメントだと思います。

于 2012-06-08T11:20:26.140 に答える
2

あなたは祝福を見たいと思うかもしれません、それはまさにあなたが望むもののようです:

祝福は呪いの制限的な仮定のいくつかを取り除き、それはあなたのコードもきれいにします

于 2012-06-08T11:21:33.053 に答える