如何在linux终端上重现类似wget的速度接口?

时间:2012-06-08 11:06:47

标签: python unix terminal stdout curses

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()

问题在于它占用了整个窗口,我一次只需要一条线。我宁愿不将所有命令行历史记录推回到终端窗口之上。如果我错了,请纠正我,但我目前认为curses应用程序总是占用整个终端窗口。

所以我查看了ttytermios模块,但我找不到任何可以做我想做的例子。

最后,我遇到了a blog post,只需在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终端?

是否有关于该主题的更好的文档,或更复杂的示例(例如,更新多行,一行多行或一行中的单个字符),最好是Python?这似乎不是Python的一个特性,而是tty,这就是为什么我猜我没找到任何东西。是否有人工页面或我应该阅读的内容?

2 个答案:

答案 0 :(得分:3)

上面的代码使用ANSI转义码:https://en.wikipedia.org/wiki/ANSI_escape_code。我认为这是您在尝试查找找到的代码时所寻找的文档。

答案 1 :(得分:2)

您可能想查看Blessings,它似乎正是您想要的:

  

Blessings提升了几个诅咒的限制性假设,它也使你的代码变得漂亮