4

I'm new to Python and Programming as well. I know from Google's python class how to run external command using:

(status, output) = commands.getstatusoutput(cmd)
if status: ## Error case, print the command's output to stderr and exit
sys.stderr.write(output)
sys.exit(1)

But I perceive that commands module is going obsolete. I want the status and the output, so I can print the output using sys.stderr.write() if there is any error. So, is there any equivalent command in subprocess module? I'm currently using:

subprocess.call(args,shell=False) now.

Thanks!

hans-t
  • 3,093
  • 8
  • 33
  • 39

4 Answers4

4

There is subprocess.getstatusoutput() in Python 3 that could be implemented as:

from subprocess import check_output, CalledProcessError, STDOUT

def getstatusoutput(cmd):
    try:
        data = check_output(cmd, shell=True, universal_newlines=True, stderr=STDOUT)
        status = 0
    except CalledProcessError as ex:
        data = ex.output
        status = ex.returncode
    if data[-1:] == '\n':
        data = data[:-1]
    return status, data

Both return status that is different from the original commands.getstatusoutput(). See Python Issue: Document & unittest the subprocess.getstatusoutput() status value.

whiteSkar
  • 1,614
  • 2
  • 17
  • 30
jfs
  • 399,953
  • 195
  • 994
  • 1,670
2

It's also possible to do this, with a bit less code

from subprocess import Popen, PIPE

def getstatusoutput(command):
    process = Popen(command, stdout=PIPE)
    out, _ = process.communicate()
    return (process.returncode, out)

code, out = getstatusoutput(["echo", "some text"])
print code
print out
comawill
  • 21
  • 2
0

Popen is a nice and easy way to do it:

from subprocess import Popen, PIPE

def local(command):
    print 'local', local
    process = Popen(command.split(), stdout=PIPE, stderr=PIPE)
    out = process.stdout.read()
    err = process.stderr.read()
    print 'out', out
    print 'err', err
    returncode = process.wait()
    if returncode:
        raise Exception(returncode, err)
    else:
        return out
Samy Arous
  • 6,794
  • 13
  • 20
  • your code deadlocks if the child process generates enough output to fill stderr's OS pipe buffer. – jfs Sep 30 '14 at 18:11
0

What getstatusoutput does is gather both stdout and stderr output interleaved in one variable. This will quite closely replicate the actual behaviour of getstatusoutput on those where it does not exist (getstatusoutput and the whole commands module was removed on Python 3 completely), excepting the newline behaviour. The resulting data is in bytes.

def getstatusoutput(cmd):
    subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    out, _ = process.communicate()

    if out[-1:] == b'\n':
        out = out[:-1]

    return (process.returncode, out)

This function returns bytes on Python 3 on purpose, as the Python 2 version returns str

  • it does not replicate actual behavior: [you need to trim the newline (and return text on Python 3)](http://stackoverflow.com/a/28483026/4279). – jfs Feb 12 '15 at 16:46