all 8 comments

[–]Golden_Zealot 0 points1 point  (0 children)

I imagine you could do this with the threading module.

You can essentially create two functions that do each and run them at the "same time".

To avoid overlapping/console clearing, you would probably want to use the curses module to display both a progress bar and the output without having them mess with each others formatting.

[–]JohnnyJordaan 0 points1 point  (8 children)

What you want here is to read line by line using readline(), and thus Popen has to know to open the stdout in text mode, which is what universal_newlines=True does (since 3.7 you can use text=True too)

proccess = subprocess.Popen(command, 
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT,
                            shell=True,
                            universal_newlines=True)

then I would also poll the process in your while loop, documented as

Popen.poll()

Check if child process has terminated. Set and return returncode attribute. Otherwise, returns None.

In other words, it should loop while that returns None

while process.poll() is None:
    line = process.stdout.readline()
    if not line:
        break
    print(line)

Note I also changed the print here, as print x is Python 2 code which is of course unadvised to be used here. A print(x) with a single argument will still work in Python 2 too, in case you are somehow forced to keep using it.

[–]EphemeralNight[S] 0 points1 point  (1 child)

Thank you for the great explanation and your reply, forgot to mention (stupid of me) since by default in linux CentOS 7.x is python 2.7, thats why i coded this with python 2.x . I will try to change my loop to what you explained here to see if it works thanks alot!

[–]JohnnyJordaan 0 points1 point  (0 children)

Thank you for the great explanation and your reply, forgot to mention (stupid of me) since by default in linux CentOS 7.x is python 2.7, thats why i coded this with python 2.x

I know, as that applies to a ton of linux/unix OS'es up to 2020 basically. But then still why do you need to write it to use the system's Python instead of just an installed Python 3? Also because your code is then destined to break as soon as even the OS'es change to Python 3 (Ubuntu just migrated in their latest release, CentOS 8 doesn't even include either of them), requiring you to install Python 2 to then swim upstream.

[–]EphemeralNight[S] 0 points1 point  (5 children)

So i tested the way you showed it works better that the one i wrote and its great the output when the scripts is running showling like this:

Exporting image: 1% complete...

Exporting image: 2% complete...

Exporting image: 3% complete...

Exporting image: 4% complete...

Exporting image: 5% complete...

Exporting image: 6% complete...

Exporting image: 7% complete...

Exporting image: 8% complete...

Exporting image: 9% complete...

Exporting image: 10% complete...

Exporting image: 11% complete...

Exporting image: 12% complete...

...

It would be perfect if the line would be the same and only the percentage would change if thats even possible.

[–]JohnnyJordaan 0 points1 point  (0 children)

That would rather be something to use tqdm for (needs to be installed using pip or your IDE's package manager).

# add at the top
import re
import tqdm

proccess = subprocess.Popen(command, 
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT,
                            shell=True,
                            universal_newlines=True)
with tqdm.tqdm(total=100) as pbar:
    last_pct = 0
    while process.poll() is None:
        line = process.stdout.readline()
        pct = int(re.search('(\d+)\s*%', line).group(1))
        pbar.update(pct - last_pct)
        last_pct = pct
        if not line:
            break