Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a Python subprocess-like call that takes a stdin input string and returns stderr, stdout, and return code?

As per the subject line, is there a standard Python 2.7 library call that I can use like this:

(returncode, stdout, stderr) = invoke_subprocess(args, stdin)

The catch is that I want all three forms of output: the returncode and the entire (and separate) content from both stdout and stderr. I expected to find something like this in the subprocess module, but the closest I can see is subprocess.check_output, which gives you two out of three (the returncode and stdout).

There are other questions on stack overflow that suggest piping stderr to stdout, but I need to keep them separate because I'm using Python to drive testing of some non-Python applications where I'm trying to distinguish which output shows up on which streams. For example, I want to verify that human-readable error messages shows up in stderr, but that only machine-parseable output data shows up on stdout.

I think what I want is a simple four-liner...

def method(args, input):
    from subprocess import Popen, PIPE
    p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
    out, err = p.communicate(input)
    return (p.poll(), out, err)

...so I'm a bit surprised that there's not already be a method like this, given the number of other methods that are mostly similar to this in the subprocess module. Does it exist and I'm missing it, or is it present somewhere in some other standard Python 2.7 module? Or is there a subtle reason why a method like this is a bad idea?

like image 517
Mickalot Avatar asked Nov 01 '22 06:11

Mickalot


1 Answers

It doesn't exist because that's what subprocess.Popen is designed to do. The other functions exist mostly to support drop-in replacement of os.system and common simplistic automation cases. Trying to cover every use case with a one-liner would result in an even more bloated set of functions.

Also note that you can use p.returncode rather than p.poll(). It's guaranteed to have been set by the time p.communicate(...) returns.

like image 57
Amber Avatar answered Nov 09 '22 11:11

Amber