Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python check_output fails with exit status 1 but Popen works for same command

Command framed to identify if Xcode is running on Mac: cmd = "ps -ax | grep -v grep | grep Xcode"

If Xcode is not running, then above command works well with Popen method of subprocess module, but raises a CalledProcessError with check_output method. I tried to inspect the stderr through the following code, but failed to get appropriate information to understand the reason.

from subprocess import check_output, STDOUT, CalledProcessError

psCmd = "ps -ax | grep -v grep | grep Xcode"
o = None
try:
    o = check_output(psCmd, stderr=STDOUT, shell=True)
except CalledProcessError as ex:
    print 'Error:', ex, o

Exception message is as follows:

Error: Command 'ps -ax | grep -v grep | grep Xcode' returned non-zero exit status 1 None

Question: Why the above command works with Popen, but fails with check_output ?

Note: Command works well with both approach, if Xcode is running.

like image 245
the.slow.one Avatar asked Feb 23 '15 13:02

the.slow.one


2 Answers

check_output() works as expected. Here's its simplified implementation in terms of Popen():

def check_output(cmd):
    process = Popen(cmd, stdout=PIPE)
    output = process.communicate()[0]
    if process.returncode != 0:
        raise CalledProcessError(process.returncode, cmd, output=output)
    return output

grep returns 1 if it hasn't found anything i.e., you should expect the exception if Xcode is not running.

Note: as the implementation shows, you can get the output even if the exception occurs:

#!/usr/bin/env python
from subprocess import check_output, STDOUT, CalledProcessError

cmd = "ps -ax | grep -v grep | grep Xcode"
try:
    o = check_output(cmd, stderr=STDOUT, shell=True)
    returncode = 0
except CalledProcessError as ex:
    o = ex.output
    returncode = ex.returncode
    if returncode != 1: # some other error happened
        raise

You could probably use pgrep -a Xcode command instead (note: starts with p) or use psutil module for a portable code:

#!/usr/bin/env python
import psutil # $ pip install psutil

print([p.as_dict() for p in psutil.process_iter() if 'Xcode' in p.name()])
like image 183
jfs Avatar answered Oct 23 '22 20:10

jfs


From the Python docs: "If the return code was non-zero it raises a CalledProcessError.". That's what happens to you when Xcode isn't running; the final grep Xcode exits with a non-zero status because grep couldn't find the string Xcode that you're looking for. Hence, check_output() will raise the exception.

BTW, I found this on the Python subprocess documentation.

like image 40
Karel Kubat Avatar answered Oct 23 '22 19:10

Karel Kubat