Search code examples
pythonmultithreadingprintingparallel-processingblock

Python - how to create multiple parallel print blocks


everyone!

I want to be able to print in Python multiple "blocks" of print statements. I will directly give an example to be easier.

Let's say I want to print the first 100 numbers and, while this is done, to have a separate print statement that keeps updating (this statement should be printed before). Basically, the output should be like this:

Output Statement 1 # <- This should keep updating to "Output Statement 2" than back to "Output Statement 1"
# and so on

Number 1 Number 2 Number 3 ....

If I want to print only "Output Statement 1" and keep updating this, it works, as long as it is the only "block" of print statements. But while "Output statement x" should be printed and updating, the second "block" of prints, where numbers from 1 to 100 should be shown, must also run.

What did I try:

I have created two functions, one for the first block and one for the second. Then, in main, I have created 2 separate threads, to which I assigned each of those 2 functions. The first thread, which should be responsible for the updated message, was set as daemon, because I want to continuously run until the program ends. I also set a sleep of a couple of seconds between the moment in which I start the first and the second thread.

Below is my code:

import time
import threading


def change_msg():

    while True:

        print("Out Message 1", end='\r', flush=True)
        time.sleep(1)
        print("Out Message 2", end='\r', flush=True)
        time.sleep(1)

def print_numbers():

    print("\n")
    print("Starting numbers...")
    for i in range(5):
        print("Number", i+1)
        time.sleep(5)
    print("Finishing numbers...")

if __name__ == "__main__":

    thread_1 = threading.Thread(target=change_msg, daemon=True)
    thread_2 = threading.Thread(target=print_numbers)
    thread_1.start()
    time.sleep(5)
    thread_2.start()

But the output I get is this one:

Out Message 1

Starting numbers...
Number 1
Number 2age 2
Number 3age 1
Number 4age 2
Number 5age 1
Finishing numbers...

I see that, even they are separate threads, the prints are overlapping.

How can I "separate" those 2 output sets, so they are independent? In case it's possible, of course.

P.S. I use Python 3.9

Thanks!


Solution

  • I this I understand your problem now. You can use the curses library to handle the output of the two threads. The curses library is a library in Python that allows for more advanced terminal handling, including the ability to control the cursor position and clear the screen.

    Here is an example of how you can use curses to separate the two output sets:

    import curses
    import time
    import threading
    def change_msg(win):
    
        while True:
            win.addstr(0,0,"Out Message 1")
            win.refresh()
            time.sleep(1)
            win.addstr(0,0,"Out Message 2")
            win.refresh()
            time.sleep(1)
    
    def print_numbers(win):
        win.addstr(1,0,"Starting numbers...")
        win.refresh()
        for i in range(5):
            win.addstr(2,0,f"Number {i+1}")
            win.refresh()
            time.sleep(5)
        win.addstr(3,0,"Finishing numbers...")
        win.refresh()
    
    
    if __name__ == '__main__':
        win = curses.initscr()
        thread_1 = threading.Thread( target = change_msg, args = (win,) ,daemon=True)
        thread_2 = threading.Thread( target = print_numbers, args = (win,))
        thread_1.start()
        time.sleep(5.0)
        thread_2.start()
    

    In this code, the change_msg function updates the message at the top of the terminal window, while the print_numbers function prints the numbers below it. The addstr method is used to add text to the terminal window at specific coordinates, and the refresh method is used to update the screen.

    I hope you find this helpfull this time ;)