Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to reproduce a wget-like speed interface on a linux terminal?
    text
    copied!<p>Wget prints out speed information to stdout in a very clear manner, where the speed is shown and refreshed whilst the file is downloaded, and a bar scrolls across the screen. I'd like to replicate this sort of output, in a Python program. How is this possible?</p> <p>I thought the <a href="http://docs.python.org/library/curses.html" rel="nofollow">curses</a> library should be able to do this; this is what I came up with:-</p> <pre><code>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() </code></pre> <p>The problem is that it takes up an entire window, and I only really need a line at a time. I'd rather not push all the command line history back above the terminal window. Please correct me if I'm wrong, but I currently think curses apps always take up the entire terminal window.</p> <p>So I had a look at the <a href="http://docs.python.org/library/tty.html" rel="nofollow">tty</a> and <a href="http://docs.python.org/library/termios.html#module-termios" rel="nofollow">termios</a> modules, but I can't find any examples doing what I want to do.</p> <p>Finally, I came across <a href="http://www.mutaku.com/wp/index.php/2011/06/python-dynamically-printing-to-single-line-of-stdout/" rel="nofollow">a blog post</a> which does it by simply writing some special characters to sys.stdout. Applying his code to my Speeder class, I came up with this:-</p> <pre><code>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') </code></pre> <p>This has fewer lines of code, which I like, but tbh I don't have a clue what's going on, or how to modify it to only update part of the line, similar to the curses.addstr function. Currently, the filename is overwritten with white-space. I could of course modify the class to construct the entire line each time from python, but I'd like to understand this in order to tailor it to my own needs.</p> <p>The author says this is possible only on VT100 terminals. So I guess this would only work on Unix terminals then? That's fine, but are there any Unix terminals that this would not work on?</p> <p>Is there better documentation on the subject, or more complicated examples (e.g. updating multiple lines, one line of many, or single characters on a line), preferably for Python? This doesn't seem like a feature of Python, but the tty, which is why I guess I've failed to find anything. Is there a man page or something I should read?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload