Jeremy Gillick
Jeremy Gillick

Reputation: 2700

Print stdout subprocess Popen and retain formatting

I'm using subprocess.Popen to call an installation script. However, when I pipe the output to the terminal, via print, it looses any of the formatting from the installation script output. For example, all terminal colors are gone and the download progress bar comes out on multiple lines.

Here's my code:

process = subprocess.Popen(
    [script],
    shell=True,
    cwd=script_dir,
    universal_newlines=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.STDOUT,
    env={
        'WORKSPACE': build_dir
    })
with process.stdout:
    for line in iter(process.stdout.readline, b''):
        print(line)

And a sample of the output (which is usually displayed as a progress bar):

You need to run "nvm install 4.2.2" to install it before using it.
Downloading and installing node v4.2.2...
Downloading https://nodejs.org/dist/v4.2.2/node-v4.2.2-darwin-x64.tar.gz...

                                                                          0.0%
                                                                          1.0%
###                                                                        4.6%
#######                                                                   10.5%
#############                                                             18.8%
###################                                                       26.5%
########################                                                  34.1%
##############################                                            41.9%
###################################                                       49.7%
#########################################                                 57.4%
##############################################                            65.2%
####################################################                      73.0%
##########################################################                80.8%
###############################################################           88.5%
#####################################################################     96.3%
######################################################################## 100.0%

Upvotes: 4

Views: 3806

Answers (2)

No need to call 'iter'. In fact, it complained when I tried this suggestion because it's expecting a string, not bytes.

This works to redirect the exact same output:

process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, universal_newlines=True)
for line in process.stdout:
    sys.stdout.write(line)
    sys.stdout.flush()

Upvotes: 1

falsetru
falsetru

Reputation: 369494

print statement prints additional newline at the end. Use sys.stdout.write instead:

import sys

...    

with process.stdout:
    for line in iter(process.stdout.readline, b''):
        sys.stdout.write(line)  # <--
        sys.stdout.flush()      # <--

BTW, you can just use subprocess.call without capturing stdout, stderr output unless you want to process the output in your program:

subprocess.call(
    [script],
    shell=True,
    cwd=script_dir,
    env={
        'WORKSPACE': build_dir
    })

Upvotes: 0

Related Questions