I came across this great replacment for the getstatusoutput() function in Python 2.* which works equally well on Unix and Windows. However, I think there is something wrong with the way the output is constructed. It only returns the last line of the output, but I can’t figure out why. Any help would be awesome.
def getstatusoutput(cmd):
"""Return (status, output) of executing cmd in a shell."""
"""This new implementation should work on all platforms."""
import subprocess
pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, universal_newlines=True)
output = "".join(pipe.stdout.readlines())
sts = pipe.returncode
if sts is None: sts = 0
return sts, output
There is a bug in this.
The call:
kicks off the process. The line:
reads the process’s stdout (if there were error output it could get jammed up, but since you did not redirect stderr this is safe; in the more general case, you need to use the
.communicate()function to avoid possible wedging). You might think: well, now that I’ve read all the output, the subprocess has clearly finished, sopipe.returncodeshould be set. But in fact, if you replace:with code that includes a diagnostic of some sort (or just delete the second line entirely), you’ll find that, at least on some systems sometimes,
stsisNone. The reason is that thesubprocessmodule has not had a chance to retrieve it yet. You should replace those lines with:to collect the result and obviate the need for the
is Nonetest. (It’s safe to call.wait()even if you’ve used.communicate()and/or already called.wait().)The
"".join(...)can be done slightly more efficiently by using just:All that said, it does get the full output for me. Perhaps you’re reading from something that uses just
'\r'for newlines and your Python was built without universal-newline support? (If I run something that produces\r-for-newline I still get all the lines, separated by actual newlines.)