python - 如何在 linux 终端上重现类似 wget 的速度界面?

标签 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,这就是为什么我想我找不到任何东西的原因。是否有手册页或我应该阅读的内容?

最佳答案

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

关于python - 如何在 linux 终端上重现类似 wget 的速度界面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10947650/

相关文章:

maven - sudo 将使用哪个 maven settings.xml 文件?

linux - 如何让终端建议自定义命令的选项?

python imshow,将特定值设置为定义的颜色

Python 命名管道行为

linux - 如果其中一个文件存在,则在 bash shell 脚本中发送电子邮件警报

linux - 比较不同列的两个文件并打印不同的列

Python 数字格式化

python - Apache Tika 排除了一些 html 标签

r - 假人的Makefile? Mac OS X

terminal - 如何为 Haxe 设置 Jeash?