Python: Command Line waiting feedback. And some Background on why!

4.2.39 Escape sequence
A string of bit combinations that is used for control purposes in code extension procedures. The first of these bit combinations represents the control function ESCAPE.
ECMA-48 Control Functions for Coded Character Sets

The situation

You are working on some script that outputs on the terminal. Also, wget, apt-get and similar software comes to your mind. They have fancy output! now you want it too.

Google a little and finish on stack overflow where someone has a magic sequence…

A Python Magic sequence of text

For Python, one of the magic sequences is:

sys.stdout.write("\r\x1b[K"+your_updated_string)

How this works?

Okay. If you just want a class to represent a rotating stick skip this part, and go to the end.

In this section, I explain what is everything on that magic sequence. First from sequence-explanation, then the other way around.

>>Sequence explanation

\r Escape sequence for a Carriage Return (Go to the beginning of the line).
\x1b[ Code for CSI (Control Sequence Introducer, nothing to do with the TV-series. check Wikipedia). It is formed by the hexadecimal escape value 1b (\x1b) followed by [.
K is the Escape sequence code to Erase the line.

>>From the beginning

I need a escape sequence to erase the line and rewrite something. In my case I want to rewrite the line with the next step on the spinner sequence.

Checking ECMA-048, the function ERASE IN LINE (section 8.3.41) seems suitable. According to the document, this control function is represented by:
CSI (Ps) 04/11
CSI is the control sequence: \x1b[. (Escape [)
(Ps) stands for Single selective Parameter (Parameter single). And in this function it has a default value of 0.

0 – the active presentation position and the character positions up to the end of the line are put into the erased state
ECMA-48 Control Functions for Coded Character Sets

The other possible Ps values deal with deleting the whole line. In this case, given that the cursor has to return at the start of the line to output the next animation step, I will just send the cursor to the beginning and then erase the line.

04/11 represents the hexadecimal value of K (0x4B). 04 is the column number and 11 the row number of the K character on an 8 bit code table. Check page 12 of ECMA-043, there’s something like:

ECMA-043 Fancy table

It is all set. The terminal has to recieve:

  • Return to start of the line (Carriage Return)
  • Delete from position to the end of the line
  • Set new step on the animation

"\r\x1b[k"+newstepchar
Ta-Dah!

Rotating Stick Class

The code and some comment is on a Git Gist here. 🙂

import sys
import threading
import time

class cSpinner(threading.Thread):
    """
        Print things to one line dynamically
    """
    chars = ["\\","|","/","-"]
    index = 0
    keeprunning = True 


    def run(self):
        while self.keeprunning:
            self.printing(self.chars[self.index%len(self.chars)])
            time.sleep(0.1)
            self.index +=1

    def printing(self,data):
        sys.stdout.write("\r\x1b[K"+data.__str__())
        sys.stdout.flush()

    def stop(self):
        self.keeprunning = False

Just create an instance of cSpinner and call start to make it run.
Maybe you want a cooler spinner, check this stack overflow thread.

References

ECMA-048 ⇒GO
ECMA-043 ⇒GO
Python Threads ⇒GO

Advertisements

1 Comment

Filed under code, curious, tips

One response to “Python: Command Line waiting feedback. And some Background on why!

  1. Pingback: DBPedia World | Castells

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s