Redirect subprocess stderr to stdout

phihag picture phihag · Jul 15, 2012 · Viewed 45.2k times · Source

I want to redirect the stderr output of a subprocess to stdout. The constant STDOUT should do that, shouldn't it?

However,

$ python >/dev/null -c 'import subprocess;\
                        subprocess.call(["ls", "/404"],stderr=subprocess.STDOUT)'

does output something. Why is that the case, and how do I get the error message on stdout?

Answer

phihag picture phihag · Jul 15, 2012

A close read of the source code gives the answer. In particular, the documentation is misleading when it says:

subprocess.STDOUT
Special value that (...) indicates that standard error should go into the same handle as standard output.

Since stdout is set to "default" (-1, technically) when stderr=subprocess.STDOUT is evaluated, stderr is set to "default" as well. Unfortunately, this means that stderr output still goes to stderr.

To solve the problem, pass in the stdout file instead of subprocess.STDOUT:

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"],
                        stderr=sys.stdout.buffer)'

Or, for compatibility with legacy 2.x versions of Python:

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"],
                        stderr=sys.stdout.fileno())'