문제

I don't know if this can be done but I'm sure I saw this in some scripts, that's why I'm asking.

I need to print a string like this one:

++++++++++++++++++++++++++++++     +++++++++++++++
+     A 1     ++     A 2     +     +     A n     +
+-------------++-------------+     +-------------+
+     B 1     ++     B 2     + ... +     B n     +
+-------------++-------------+     +-------------+
+     C 1     ++     C 2     +     +     C n     +
++++++++++++++++++++++++++++++     +++++++++++++++

where n is the number of columns and it depends on user's input. The A row is fixed, while B and C has to change while the program goes.

So, first of all I need a way to print this kind of string, knowing that A and B are strings with length of 8 but C goes from 8 to 1 char.

I took a look at the various "formatter" solutions and to ppretty but they seem way too far from what I need (and I didn't found a lot of examples!). (I've just tried ppretty because the other solutions required something like a data source while I'm getting my data with class.getData() since I'm coming from Java!)

Now, after printing this string, I want it to be updated as B and C changes, without printing it again to avoid a lot of printed stuff and to make everything tidier and easier to be read.

Is there any way to do that?

edit:

This is what I've tried (with no success)

def printCrackingState(threads):
info_string = '''
++++++++++++++++++++++++++++++++++
+ Starting password = s.%08d +
+--------------------------------+    
+ Current pin       = s.%08d +
++++++++++++++++++++++++++++++++++
+ Missing pins      =   %08d +
++++++++++++++++++++++++++++++++++
              '''
while 1:
    for t in threads:
        printed_string = info_string % (t.starting_pin, t.testing_pin, t.getMissingPinsCount())
        sys.stdout.write(printed_string)
    time.sleep(3500)

and this is the result:

++++++++++++++++++++++++++++++++++
+ Starting password = s.00000000 +
+--------------------------------+    
+ Current pin       =   00000523 +
++++++++++++++++++++++++++++++++++
+ Missing pins      =   01249477 +
++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++
+ Starting password = s.01250000 +
+--------------------------------+    
+ Current pin       =   01250491 +
++++++++++++++++++++++++++++++++++
+ Missing pins      =   01249509 +
++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++
+ Starting password = s.02500000 +
+--------------------------------+    
+ Current pin       =   02500465 +
++++++++++++++++++++++++++++++++++
+ Missing pins      =   01249535 +
++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++
+ Starting password = s.03750000 +
+--------------------------------+    
+ Current pin       =   03750564 +
++++++++++++++++++++++++++++++++++
+ Missing pins      =   01249436 +
++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++
+ Starting password = s.05000000 +
+--------------------------------+    
+ Current pin       =   05000592 +
++++++++++++++++++++++++++++++++++
+ Missing pins      =   01249408 +
++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++
+ Starting password = s.06250000 +
+--------------------------------+    
+ Current pin       =   06250579 +
++++++++++++++++++++++++++++++++++
+ Missing pins      =   01249421 +
++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++
+ Starting password = s.07500000 +
+--------------------------------+    
+ Current pin       =   07500577 +
++++++++++++++++++++++++++++++++++
+ Missing pins      =   01249423 +
++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++
+ Starting password = s.08750000 +
+--------------------------------+    
+ Current pin       =   08750555 +
++++++++++++++++++++++++++++++++++
+ Missing pins      =   01249445 +
++++++++++++++++++++++++++++++++++

I've used sys.stdout.write() to have them on the same line but it doesn't work!

edit 2:

My second attemp is with curses, as suggested in the replies.

I can write things on the same line but they don't get updated.

Here's my code:

import curses
import time
import threading

class CursesPrinter(threading.Thread):
    windows = []
    screen = None 
    processes = []   

    info_string = '''
    +++++++++++++++++++++++++
    + Starting = s.%08d +
    +-----------------------+    
    + Current  = s.%08d +
    +-----------------------+
    + Missing  =   %08d +
    +++++++++++++++++++++++++
                  '''            

    def _makeWindows(self, numWindows):
        x = 0
        y = 0
        height = 15
        width = 30        
        for i in range(numWindows):
            win = curses.newwin(height, width, x, y)
            #win.border(1)
            y+=width
            if y>self.screen.getmaxyx():
                #This should make a new line if we reach the end of the terminal
                y = 0
                x+=height
            self.windows.append(win) 

    def run(self):
        while 1:
            for i in range(len(self.processes)-1):
                print_string = self.info_string % (self.processes[i].starting_pin, self.processes[i].testing_pin, self.processes[i].getMissingPinsCount())                
                self.windows[i].addstr(0,0, print_string)
                self.windows[i].refresh()
        #time.sleep(60)                            


    def __init__(self, threads, processes):
        super(CursesPrinter, self).__init__()
        self.screen = curses.initscr()
        curses.curs_set(0)
        self.processes = processes
        self._makeWindows(threads)       
        #curses.endwin()  
도움이 되었습니까?

해결책

A quick-and-dirty method that relies on your terminal handling VT100 escape sequences is to clear the screen and then move the cursor to the home position before printing the output.

A quick demo:

import sys
import time
import random

ESC = "\x1b"

def home():
    sys.stdout.write(ESC + '[0;0H')
    sys.stdout.flush()

def cls():
    sys.stdout.write(ESC + '[2J')
    sys.stdout.flush()

def print_status():
    w = 8
    print('+' + '-'*w + '+')
    for row in range(3):
        fmt = '|%%%dd |' % (w - 1)
        print(fmt % random.randint(0, 1000))
        print('+' + '-'*w + '+')
    sys.stdout.flush()

if __name__ == "__main__":
    cls()
    for k in range(16, 0, -1):
        home()  # or use cls()
        print_status()
        time.sleep(0.5)

Instead of using the "home" sequence, you could keep track of how many lines you printed, and print that many "cursor up" escape sequences before printing the next update.

If you want to get fancier, check out the python curses module, blessings, or urwid.

I don't think any of those work in a regular Windows terminal; that's why I asked about the OS you were targeting.

다른 팁

You could just print out a lot of new line characters to make it look like the screen has been cleared. Also its easy to implement and helpful for debugging.

The code would be some thing like:

print "\n"*100

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top