In a related question, I asked where to find the documentation for the C function "wait." This was an attempt to figure out return codes for the commands.getstatusoutput() module. Stackoverflow came through, but the documentation didn't help. Here's what puzzles me:
#!/usr/bin/python
import commands
goodcommand = 'ls /'
badcommand = 'ls /fail'
status, output = commands.getstatusoutput(goodcommand)
print('Good command reported status of %s' % status)
status, output = commands.getstatusoutput(badcommand)
print('Bad command reported status of %s' % status)
When run on OS X (Leopard) I get the following output: (Which matches the documentation.)
$ python waitest.py
Good command reported status of 0
Bad command reported status of 256
On OS X, doing an "ls /fail ; echo $?" gets the following output:
$ ls /fail ; echo $?
ls: /fail: No such file or directory
1
When run on Linux (Ubuntu Hardy) I get the following output:
$ python waitest.py
Good command reported status of 0
Bad command reported status of 512
On Ubuntu, doing "ls /fail" gets a 2:
$ ls /fail ; echo $?
ls: cannot access /fail: No such file or directory
2
So Python appears to be multiplying status codes by 256. Huh? Is this documented somewhere?
The function getstatusoutput() runs a command via the shell and returns the exit code and the text output (stdout and stderr combined). The exit codes are the same as for the C function wait() or os.
A. Some common Python commands are input, print, range, round, pip install, len, sort, loop commands like for and while so on and so forth.
How to Start a Process in Python? To start a new process, or in other words, a new subprocess in Python, you need to use the Popen function call. It is possible to pass two parameters in the function call. The first parameter is the program you want to start, and the second is the file argument.
There is a set of functions in os
module (os.WIFCONTINUED
, os.WIFSTOPPED
, os.WTERMSIG
, os.WCOREDUMP
, os.WIFEXITED
, os.WEXITSTATUS
, os.WIFSIGNALED
, os.WSTOPSIG
), which correspond to macros from wait(2) manual. You should use them to interpret the status code.
For example, to get the exit code you should use os.WEXITSTATUS(status)
A better idea would be to switch to subprocess
module.
Wow. The insight that it was multiplying by 256 got me there. Searching for "python commands +256" got me to a Python Module Of The Week article which explains what's going on.
Here's a snippet from that page:
The function getstatusoutput() runs a command via the shell and returns the exit code and the text output (stdout and stderr combined). The exit codes are the same as for the C function wait() or os.wait(). The code is a 16-bit number. The low byte contains the signal number that killed the process. When the signal is zero, the high byte is the exit status of the program. If a core file was produced, the high bit of the low byte is set.
And some of Doug's code:
from commands import *
def run_command(cmd):
print 'Running: "%s"' % cmd
status, text = getstatusoutput(cmd)
exit_code = status >> 8
signal_num = status % 256
print 'Signal: %d' % signal_num
print 'Exit : %d' % exit_code
print 'Core? : %s' % bool(exit_code / 256)
print 'Output:'
print text
print
run_command('ls -l *.py')
run_command('ls -l *.notthere')
run_command('echo "WAITING TO BE KILLED"; read input')
Looking at commands.py
:
def getstatusoutput(cmd):
"""Return (status, output) of executing cmd in a shell."""
import os
pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r')
text = pipe.read()
sts = pipe.close()
if sts is None: sts = 0
if text[-1:] == '\n': text = text[:-1]
return sts, text
We see sts
holds the value of os.popen(...).close()
. Looking at that documentation, os.popen(...).close()
returns the value of os.wait
:
os.wait()
Wait for completion of a child process, and return a tuple containing its pid and exit status indication: a 16-bit number, whose low byte is the signal number that killed the process, and whose high byte is the exit status (if the signal number is zero); the high bit of the low byte is set if a core file was produced. Availability: Unix.
Emphasis was mine. I agree that this "encoding" isn't terribly intuitive, but at least it was fairly obvious at a glance that it was being multiplied/bit-shifted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With