Home > front end >  How to make multiline progress indicator in terminal
How to make multiline progress indicator in terminal

Time:03-06

I'm trying to create a progress display in terminal, This is what i done

import time
dots = ['', '.', '..', '...']
for i in range(11):
    print(f'\rtime: {i} sec\t\tEstimated time: 10 sec', end='', flush=True)
    if(i != 10):
        print(f'\rStatus: copying{dots[i%4]}', end='', flush=True)
    else:
        print(f'\rStatus: done!!!')
    time.sleep(1)

I want something like this,
enter image description here

But this my current output looks like,
enter image description here

How to make it in two lines and update only the time and status string

if i try like this,

import time
dots = ['', '.', '..', '...']
for i in range(1, 11):
    print(f'\rtime: {i} sec\t\tEstimated time: 10 sec', flush=True)
    if(i != 10):
        print(f'\rStatus: copying{dots[i%4]}', flush=True)
    else:
        print(f'\rStatus: done!!!')
    time.sleep(1)

the ouput looks like this,
enter image description here

CodePudding user response:

The issue with the two lines is that it goes beyond the capabilities of what \r can do for you. Probably the only way you can do what you want is using ANSII escape characters. Here it is spelled out:

for i in range(11):
    print(f'time: {i} sec\t\tEstimated time: 10 sec')
    if i != 10:
        print(f'Status: copying{("." * (i % 4)).ljust(3)}')
        print('\033[3F')
    else:
        print('\033[2F')
        print(f'\nStatus: done!!!    ')
    time.sleep(1)

Let's go over it: The \033 character is the octal value for the ASCII escape character. The next character ([) indicates that the next command is from the CSI group of commands. CSI stands for Control Sequence Introducer and sets the scene for the next command. The number is the number of rows to go up and the F character means 'move n lines up'.

Note that this only works in a terminal that allows these escape chars. This is true for most terminals, however, it might just not be true for a debug terminal in your IDE (if you are using one).

CodePudding user response:

If you don't want external libraries, as @Schottky suggested would be to use ANSII escape character, but this wouldn't work on OSs like Windows cmd (probably OP's), to enable that you would use ctypes, you can eneble that by simply doing:

import ctypes

kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)

and then, improvin:

secs=11
for i in range(secs):
    print(f'time: {i} sec\t\tEstimated time: {secs-i} sec')
    print(f'Status: copying{("." * (i % 4)).ljust(3)}')
    print('\033[3F')
    sleep(1)
print('\033[2F')
print('Status: done!!!')

but if you want to do it with external libs, you should see tqdm:

it can be installed with

> $ pip install tqdm

Code:

from tqdm import tqdm
from time import sleep
for x in tqdm(range(11),"Copying",11):
    sleep(1)
else:
    print("Done!")

out:

Copying: 100%|██████████████████████████████████████████████████████████████████| 11/11 [00:11<00:00,  1.01s/it]
Done!
  • Related