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.