Python - Run the next command without waiting for the end of the first

Asked

Viewed 427 times

3

Good evening, everyone.

I have the following function to create a bar Progress:

def progress_bar(p_value, p_max: int):
    """
    :70 = É o tamanho da barra
    :param p_value: Valor que está sendo iterado de um laço de repetição
    :param p_max: É a quantidade total do dados que está sendo iterado
    :return:
    """
    chars = int(p_value * 40 / float(p_max))
    percent = int((p_value / float(p_max)) * 100)
    sys.stdout.write("  ") + sys.stdout.write("#" * chars)
    sys.stdout.write(" " * (40 - chars + 2))
    if p_value >= p_max:
        sys.stdout.write("done. \n\n")
    else:
        sys.stdout.write("[%3i%%]\r" % percent)
        sys.stdout.flush()

Now I need to call it inside the loop below so that the bar is inside the frame created by the top and bottom print. The top print is fine, creates good, but the bottom one only creates after the loop is finished.

How do I make it all together and load the bar Progress inside the square?

is more for the sake of aesthetics.

print(" ╔════════════════════════════════════════════════════════════════════════════╗")
for i, item in enumerate(p_list):
    progress_bar(i + 1, len(p_list))
    print(" ║ " + item.ljust(75) + "║")
print(" ╚════════════════════════════════════════════════════════════════════════════╝")

Grateful for the support.

  • What is the usual value of p_list?

  • The progressi_bar p_list is an integer received by Len(), which in this case comes from a list.

  • I guess I didn’t quite understand your question... you want '##############################################done. ' to appear after the last print?

  • No. I need you to create the frame, that is the first print and the last print and continue running the progressi_bar appearing gradually, usually the ########

  • 'normally ######'....? If you do if p_value > p_max the rectangle is created normally (but without the #####). Do jeito que está ''######################################## done. ' appears before the last two prints (last item in the list and bottom of the rectangle). You can be a little more specific?

  • I don’t know how to be more specific than that. I’m just trying to make the progressi_bar look better. Not to appear the # alone in a vacuum, you see. Make them appear inside a square.

  • I think I got it.

  • Good. I’m looking forward to it.. I’m still trying something here too.

  • I think I understand the problem, but I don’t know very well the sys library and my test script is exhibiting a strange behavior (it only enters Else if I put a print in there...). Anyway, have you ever tried to work the line that writes ##? Something like sys.stdout.write(" ") + sys.stdout.write(" " + ("#" * chars) + "". ljust(75 - chars) + "")

  • I’ll test that suggestion.

  • I found something similar in the English stack but it’s too much for my tic and tic and I couldn’t apply it. https://stackoverflow.com/questions/21239032/print-2-lines-in-the-console-concurrently-in-python

Show 6 more comments

1 answer

5


Note 1: I’ll assume your terminal supports ANSI.

Note 2: For simplicity’s sake, I’m not going to go into threads in that answer.

The function print Python (and most programming languages) receives a text and writes it in the terminal from left to right, from top to bottom (i.e., sequentially). In the case of your progress bar, you need to change this behavior so that you can manually enter the position of each character.

First of all, let’s create a function that clears the terminal screen. You didn’t say which operating system you are using, so it follows a portable function (Windows and Unix):

def limpar_tela():
    os.system('cls' if os.name == 'nt' else 'clear')

Now to the most important function: One print that receives the row and column.

def print_at(x, y, texto):
    print(f'\033[{y};{x}H{texto}')

Example: The call print_at(1, 1, 'G') will write a G in the first row and first column of your terminal (i.e., the top left corner).

Now a simple tie for allows you to create the progress bar. We can use the function time.sleep to simulate a short wait in order to view the filling progress bar.

limpar_tela()

print(" ╔════════════════════════════════════════════════════════════════════════════════════════════════════╗")
print(" ║                                                                                                    ║")
print(" ╚════════════════════════════════════════════════════════════════════════════════════════════════════╝")
print()
print(" Progresso: ")

for x in range(100):
    print_at(x + 3, 2, 'X')
    print_at(13, 5, f'{x + 1}%')
    time.sleep(0.03)

print()

Follow the full code:

import os
import time

def limpar_tela():
    os.system('cls' if os.name == 'nt' else 'clear')

def print_at(x, y, texto):
    print(f'\033[{y};{x}H{texto}')

def main():
    limpar_tela()

    print(" ╔════════════════════════════════════════════════════════════════════════════════════════════════════╗")
    print(" ║                                                                                                    ║")
    print(" ╚════════════════════════════════════════════════════════════════════════════════════════════════════╝")
    print()
    print(" Progresso: ")

    for x in range(100):
        print_at(x + 3, 2, 'X')
        print_at(13, 5, f'{x + 1}%')
        time.sleep(0.03)

    print()

if __name__ == '__main__':
    main()

Additional reading:

  • Wow, that’s amazing, I ran here and that’s what I’m wanting. I deeply appreciate it. If you’re not going to abuse your kindness in helping. These very pythonic processes, let’s say, are little complicated for my head to understand and I do not know enough English to read the documentation deeply, something I even understand. I need help filling in the middle line:

  • print(" ╔════════════════════════════════════════════════════════════════════════════════════════════════════╗")
 print(" ║")
 print(" ╚════════════════════════════════════════════════════════════════════════════════════════════════════╝") The middle line, the beginning I put, but the end to appear closed so at first I could not. If you can clarify the line: def print_at(x, y, text): print(f' 033[{y};{x}H{text}') I don’t understand what 033[{y};{x}H{text};

  • Trying to read the documentation of the link: http://www.termsys.demon.co.uk/vtansi.htm I believe I understand: does it check:? o " 33" is the ANSI code for <ESC> The '[{y}' indicates that it will start at the given position of the prints The "{x}H{text}" indicates that it will start at the beginning of the second line. Now I don’t understand this line: print_at(105, 2, f'{x + 1}%') E how to put the vertical bar to start closed the print on the second line.

  • @Clebernandi The instruction print_at(105, 2, f'{x + 1}%') type the percentage of the progress bar. The first parameter is the column, the second is the row, the third is the text. That is, You will write the percentage in column 105 of the second row.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.