Search code examples
pythonsubprocessstdoutpopenstderr

For subprocess.stderr=STDOUT - Is stdout=PIPE better than stdout="a_file_name"?


[EDITED]
2 options for handling standard output from subprocess.Popen are stdout="a_file_name" and stdout=subprocess.PIPE.
stderr can be combined with either of those via stderr=subprocess.STDOUT.

For what I'm currently doing (fuzz-testing), my resulting stdout="a_file_name" code is slightly shorter and cleaner.

However, from what I’ve seen, it seems that stdout=PIPE is often preferred by others, but I’m not sure of all of the reasons why.

If the cmd used in Popen([cmd, arg], ...) is an external executable which writes error output to stderr, is stdout=PIPE somehow better than stdout="a_file_name"?

What are some pros and cons of each?

  • In my particular context (see code snippets below), 1 advantage I can see to using stdout=PIPE rather than stdout="a_file_name" is that the former would let me easily skip writing an empty file.
  • In the event of a cmd crash, might 1 of the 2 somehow be more likely to get all of the error output?

Although I have my particular context in mind, I'd be interested in knowing the answer(s) for the more general case as well.

To better explain my context, here are my 2 alternative code segments:

import subprocess
import sys

assert sys.version_info >= (3, 3)
    # timeout added for subprocess's wait() and communicate() in Python 3.3.

with open('sub_proc1.outerr', 'w') as f_outerr1:
    sub_proc1 = subprocess.Popen([cmd, args], stdout=f_outerr1,
                                 stderr=subprocess.STDOUT,
                                 universal_newlines=True)
    try:
        return_code = sub_proc1.wait(timeout=10)
        print('*** %s CRASHED with return code: %d.' % (cmd, return_code))
    except subprocess.TimeoutExpired:
        print('*** %s succeeded.' % cmd)
        sub_proc1.kill()

versus:

...
with open('sub_proc2.outerr', 'w') as f_outerr2:
    sub_proc2 = subprocess.Popen([cmd, args], stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT,
                                 universal_newlines=True)
    try:
        (sub_proc2_out, sub_proc2_err) = sub_proc2.communicate(timeout=10)
        print('*** %s CRASHED with return code: %d.' %
              (cmd, sub_proc2.poll()))
        assert sub_proc2_err is None
            # Since stderr was redirected to STDOUT, this should be None.
        f_outerr2.write(str(sub_proc2_out or ""))
            # Treat 'None' as an empty string).
    except subprocess.TimeoutExpired:
        print('*** %s succeeded.' % cmd)
        sub_proc2.kill()

ORIGINAL POST:

TITLE: subprocess: Pros and cons of stderr=STDOUT vs. stderr=PIPE?

The 2 principal alternatives for handling error output from 'subprocess.Popen' seem to be 'stderr=STDOUT' (with 'stdout="some_file"') and 'stderr=PIPE'.

For what I want to do (fuzz-testing), my resulting 'stderr=STDOUT' code is a little shorter and cleaner.

However, from what I've read, it seems that 'stderr=PIPE' is preferred, but I'm not sure of all of the reasons why.

If the 'cmd' used is an external executable which writes error output to 'stderr', what are the pros and cons of using 'stderr=STDOUT' versus 'stderr=PIPE'?

...


Solution

  • Writing to a specific file means that your program will have conflicts if it is run more than once at a time since both processes will want to write to the same file. (search for issues with temporary file creation and security vulnerabilities)

    Using a pipe means there is no issue of file name uniqueness.

    Do you care about the output? If not, then use subprocess.DEVNULL and it will discard the output for you.