Rewrite Multiple Lines in the Console

Rewrite multiple lines in the console

On Unix, use the curses module.

On Windows, there are several options:

  • PDCurses: http://www.lfd.uci.edu/~gohlke/pythonlibs/
  • The HOWTO linked above recommends the Console module
  • http://newcenturycomputers.net/projects/wconio.html
  • http://docs.activestate.com/activepython/2.6/pywin32/win32console.html

Simple example using curses (I am a total curses n00b):

import curses
import time

def report_progress(filename, progress):
"""progress: 0-10"""
stdscr.addstr(0, 0, "Moving file: {0}".format(filename))
stdscr.addstr(1, 0, "Total progress: [{1:10}] {0}%".format(progress * 10, "#" * progress))
stdscr.refresh()

if __name__ == "__main__":
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()

try:
for i in range(10):
report_progress("file_{0}.txt".format(i), i+1)
time.sleep(0.5)
finally:
curses.echo()
curses.nocbreak()
curses.endwin()

How to overwrite multiline print in Python?

Use some ANSI escape codes to control your terminal: (from https://stackoverflow.com/a/11474509/8733066)
"\033[F" makes the terminal cursor go up one line, *3 is because there are 3 lines

def status(num, counter):
print("\033[F"*3)
print(
f'Current number {num}',
f'Numbers done: {counter}, all nums: {all_nums}',
f'{(num/all_nums):2.1%}',
sep="\n"
)

# call this before the for loop:
print("\n"*3, end="")

How to rewrite on several terminal lines in Python

It'll depend on the terminal emulator you use, but you probably want the ANSI 'cursor up' codes to be output, which will move the cursor up ready for the next iteration. The code you want is "ESCAPE [ A"

import time

for n in range(1, 10):
print(n)
print(n*2)
time.sleep(1)
print("\033[A\033[A", end="")

An ESCAPE is character 27, which is 033 in octal.
Note the end="" to stop the cursor moving down again...

C++ - Overwrite Multiple Lines that were Previously Output to Console

You can use SetConsoleCursorPosition to set the cursor position.

Python 3 Print Update on multiple lines

\r is a carriage return, where the cursor moves to the start of the line (column 0). From there, writing more text will overwrite what was written before, so you end up only with the last line (which is long enough to overwrite everything you've written before).

You want \n, a newline, which moves to the next line (and starts at column 0 again):

print("Orders: " + str(OrderCount) + "\nOperations: " + str(OperationCount), end="\n\n")

Rather than use str() and + concatenation, consider using string templating with str.format():

print("Orders: {}\nOperations: {}\n".format(OrderCount, OperationCount))

or a formatted string literal:

print(f"Orders: {OrderCount}\nOperations: {OperationCount}\n")

If you wanted to use \r carriage returns to update two lines, you could use ANSI control codes; printing \x1B[2A (ESC [ 2 A) moves the cursor up 2 times, adjust the number as needed. Whether or not this works depends on what platform you are supporting.

On my Mac, the following demo works and updates the two lines with random numbers; I used the ESC [ 0 K to make sure any remaining characters on the line are erased:

import random, time

orders = 0
operations = 0

UP = "\x1B[3A"
CLR = "\x1B[0K"
print("\n\n") # set up blank lines so cursor moves work
while True:
orders += random.randrange(1, 3)
operations += random.randrange(2, 10)

print(f"{UP}Orders: {orders}{CLR}\nOperations: {operations}{CLR}\n")

time.sleep(random.uniform(0.5, 2))

Demo:

Animated GIF demonstrating 2 lines updating several times

You could also switch to a full-terminal control with Curses or stick to putting everything on one line. If you are going to go the Curses route, take into account that Windows compatibility is sketchy at best.

Terminal - How to overwrite many lines?

The colorama third party module has support for changing the position of the cursor, via the "\x1b[?:?H" command string. You can also clear the screen this way.

import colorama
colorama.init()
def put_cursor(x,y):
print "\x1b[{};{}H".format(y+1,x+1)

def clear():
print "\x1b[2J"

clear()
put_cursor(0,0)
print "hello"
print "huhu"
#return to first line
put_cursor(0,0)
print "noooooo"

The module appears to do this by importing ctypes and invoking windll.kernel32.SetConsoleCursorPosition. See win32.py, line 58.

Replace multi-line string in terminal

You haven't specified if you need solution working on Linux or Windows.

For Linux you can use zwer answer. However curses module is not available on Windows.

Windows cmd is very simple and doesn't understand advanced formatting.
You have clear and redraw the whole window to get animation.

Here is an example of a star moving randomly on board for 20 frames of animation:

import os
import time
import random
import copy

board = [['+', '-', '-', '-', '-', '-', '-', '-', '-', '+'],
['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
['|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'],
['+', '-', '-', '-', '-', '-', '-', '-', '-', '+']]

for i in range(20):
os.system('cls')
frame = copy.deepcopy(board)
frame[random.randint(1, 8)][random.randint(1, 8)] = '*'
print('\n'.join([''.join(i) for i in frame]))
time.sleep(1)


Related Topics



Leave a reply



Submit