Wget会在文件下载时以非常清晰的方式将速度信息打印到stdout,其中速度显示并刷新,屏幕上滚动着一个进度条。我想在Python程序中复制这种输出方式。这是否可能?
我认为curses库应该能够做到这一点;以下是我想到的:-
问题在于它占用了整个窗口,而我只需要一行。我不想把所有的命令行历史记录都推到终端窗口上方。请纠正我如果我错了,但我目前认为curses应用程序总是占用整个终端窗口。
所以我看了一下tty和termios模块,但我找不到任何做我想做的事情的例子。
最后,我发现一个博客文章通过向sys.stdout写入一些特殊字符来完成此操作。将他的代码应用到我的Speeder类中,我得到了这个:-
这段代码行数较少,我喜欢这一点,但是说实话,我不知道正在发生什么,也不知道如何修改它以仅更新行的一部分,类似于curses.addstr函数。目前,文件名被覆盖为白色空格。当然,我可以修改类以每次从Python构造整个行,但我想理解它以便根据自己的需要进行调整。
作者说这只有在VT100终端上才可能。那么我猜这只能在Unix终端上工作?那很好,但是有没有任何Unix终端无法使用这个功能?
关于此主题是否有更好的文档或更复杂的示例(例如,更新多行,其中一行中的一行或单行中的单个字符),最好是针对Python?这似乎不是Python的一个特性,而是tty,这就是我猜测为什么我找不到任何东西的原因。是否有man页或其他应该阅读的内容?
我认为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应用程序总是占用整个终端窗口。
所以我看了一下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终端无法使用这个功能?
关于此主题是否有更好的文档或更复杂的示例(例如,更新多行,其中一行中的一行或单行中的单个字符),最好是针对Python?这似乎不是Python的一个特性,而是tty,这就是我猜测为什么我找不到任何东西的原因。是否有man页或其他应该阅读的内容?
update
方法中的转义码替换为"\033[15D"
,让我可以将光标向后移动 15 个字符。然后我就可以覆盖已经存在的内容了。完美! - Alex Leach