Joshua Fox
Joshua Fox

Reputation: 19655

How do I stream a subprocess's stderr while returning stdout as string?

I'd like to capture standard output as a string when running a subprocess from Python 3.9. At the same time, I would like standard error to stream to my console for debugging that lengthy subprocess.

Popen.communicate() has related functionality, but it seems that subprocess, as a high-level API, is preferable; and I am not sure how to treat the two streams separately.

This code returns the two of them as strings. How can I just stream stderr?

process = subprocess.run( ['sh', script], capture_output=True, text=True, env=env)
if process.returncode:
     raise Exception(f"Error {process.returncode} {process.stderr}")
return process.stdout

Upvotes: 1

Views: 338

Answers (1)

larsks
larsks

Reputation: 311556

If you read the documentation, you'll note that capture_output is not what you want:

If capture_output is true, stdout and stderr will be captured.

If you want to capture stdout but not stderr, just set stdout=subprocess.PIPE. If I have a script named script.sh that contains:

#!/bin/sh

echo "This is normal output"
echo "This is an error" >&2

I can capture the output like this:

>>> res = subprocess.run(['sh', 'script.sh'], stdout=subprocess.PIPE)
This is an error
>>> res.stdout
b'This is normal output\n'

Output on stderr showed up on the console, while output to stdout was captured in res.stdout.

Upvotes: 2

Related Questions