4

For example, I have a command commandA and want to get the the exit code after commandA is executed. CommandA is expected to be failed, so the exit code we should get is 1.

If I type command in the terminal as commandA;echo $?, a 1 get displayed on the screen. However, when I do it with python, things went wrong.

I have tried to call commandA with os.system(commandA) or subprocess.call(commandA.split()), and then call os.popen('echo $?').read(), results are 0.

os.popen('commandA;echo $?').read() gives me a correct result but the process of commandA is not displayed in the screen, which is what I don't want it happens.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Jieke Wei
  • 303
  • 1
  • 4
  • 12
  • Duplicate of: https://stackoverflow.com/questions/1696998/what-is-the-return-value-of-subprocess-call – The Pjot May 25 '18 at 13:48
  • Are you running Python scripts in-line on command line? The shell interpreter will expand $? early, before passing the string to Python. `$ python -c "import os; os.system('echo test; false; echo $?')" test 0` `$ python -c "import os; os.system('echo test; false; echo \$?')" test 1` – eel ghEEz May 25 '18 at 13:52

2 Answers2

10

subprocess.call returns the exit code directly:

exit_code = subprocess.call(commandA.split())

The reason your attempts with echo $? are not working is that both echo (typically) and $? (certainly) are constructs of the shell, and don't exist in Python.

Thomas
  • 174,939
  • 50
  • 355
  • 478
  • oh! Thanks a lot! it works. So what python does is not just copying the exactly same command to the terminal and call it? – Jieke Wei May 25 '18 at 13:55
  • It depends. If you pass a string (just `commandA`) and set `shell=True`, then Python sends it to the shell (typically bash). But then you also have the usual shell troubles with quoting, whitespace, escaping, etc., so in general this is not recommended. If, on the other hand, you pass the command as a list (`commandA.split()`), Python doesn't use the shell and goes directly to the kernel. (The _terminal_ is just the program that shows the input/output of programs on your screen, and doesn't enter the picture here.) – Thomas May 25 '18 at 13:59
2

It kind of depends on python version. You can do:

result=subprocess.check_output(['commandA'],Shell='True')

For 3.x you do:

result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)

Or you can do with a try catch to see only errors. Something like:

try:
    output = subprocess.check_output(["command"])
except subprocess.CalledProcessError as e:
    errorCode = e.returncode
Veselin Davidov
  • 7,031
  • 1
  • 15
  • 23