85

I came across this:

>>> import os
>>> os.system('ls')
file.txt README
0

What is return value of os.system()? Why I get 0?

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
  • `os.system("ls")` is for running a command where you only care if it ran or not. If you want the stdout output, use something like `commands.getstatusoutput("ls")[1]` as defined here: https://docs.python.org/2/library/commands.html – Eric Leschinski Jul 14 '16 at 15:05
  • 1
    (But `os.system("ls")` will, however, output the result of an `ls` if you do not take steps otherwise. I'm not sure in this case that you would want to suppress the additional output, but if you did, one approach would be `os.system("ls > /dev/null 2>&1")`. – Christos Hayward Nov 04 '17 at 09:49
  • 1
    Just to spell out the obvious, the documentation for `os.system` pretty clearly recommends that you avoid it in favor of `subprocess`. There is one function to just run a command and return its result code (`subprocess.call`) and one to retrieve the output from a command (`subprocess.check_output`) as well as one which fails if the command fails (`subprocess.check_call`). There is a modern higher-level function `subprocess.run` which does all three, and more. – tripleee Dec 23 '20 at 08:24

5 Answers5

83

The return value of os.system is OS-dependant.

On Unix, the return value is a 16-bit number that contains two different pieces of information. From the documentation:

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)

So if the signal number (low byte) is 0, it would, in theory, be safe to shift the result by 8 bits (result >> 8) to get the error code. The function os.WEXITSTATUS does exactly this. If the error code is 0, that usually means that the process exited without errors.

On Windows, the documentation specifies that the return value of os.system is shell-dependant. If the shell is cmd.exe (the default one), the value is the return code of the process. Again, 0 would mean that there weren't errors.

For others error codes:

rubik
  • 8,814
  • 9
  • 58
  • 88
  • OS maintains an errno as variable which has the exit status of recently executed process. erron is global , this errno value is returned after execution which states whether cmd executed successfully or failed – deepak Jan 28 '14 at 10:49
  • This isn't an answer, and the Linux link doesn't go anywhere useful now. – Steve Bennett Jun 02 '16 at 02:59
  • 2
    @SteveBennett Thanks, I fixed the link. Why do you think it does not qualify as an answer? The question was "what is this number", I gave the answer. – rubik Jun 02 '16 at 07:36
  • Because the important bit is only on the external websites, instead of summarised here. – Steve Bennett Jun 03 '16 at 05:15
  • 1
    @SteveBennett The most important one is 0 (it has the same meaning across systems), while all the others depend on the system. Hence the links. If I had to add a summary I would have to add a table with some (arbitrary?) codes from both pages. This is probably not needed, since most of the readers are interested in the returns code of one platform. – rubik Jun 03 '16 at 07:03
  • This is completely wrong. The latter 8 bits are the return code. Anyone trying to write code that handles system call errors in a sane way based on this answer will have some very confusing bugs. e.g. `sys.exit(os.system(exit 2))` has exit code 0 on both Ubuntu and OSX. – brandones Dec 09 '16 at 20:01
  • Actually, further, `sys.exit(os.system('exit ' + n))` exits 0 for any valid value of `n` (0+). The return value goes in the left 8 bits of the 16-bit integer that gets returned, so `os.system('exit 1')` gives 256, and every other return value is a multiple of 256. But system return codes are modulo 256. – brandones Dec 09 '16 at 20:23
  • (Sorry, my first comment should say "The first 8 bits"). – brandones Dec 09 '16 at 22:26
  • 1
    @brandones Thanks for pointing that out. This answer was written ages ago and it clearly was missing important information. It should be correct now. – rubik Dec 10 '16 at 10:28
  • 7
    Solid. Sorry about the tone, I had just spent a while grappling with exactly such a bug. Note that you can use `os.WEXITSTATUS(os.system(command))` to get the exit status. – brandones Dec 10 '16 at 17:27
  • @brandones No worries! That function is not really well known, so I'll add it to the answer. – rubik Dec 10 '16 at 17:37
35

os.system('command') returns a 16 bit number, which first 8 bits from right(lsb) talks about signal used by os to close the command, Next 8 bits talks about return code of command.

00000000    00000000
exit code   signal num

Example 1 - command exit with code 1

os.system('command') #it returns 256
256 in 16 bits -  00000001 00000000
Exit code is 00000001 which means 1

Example 2 - command exit with code 3

os.system('command') # it returns 768
768 in 16 bits  - 00000011 00000000
Exit code is 00000011 which means 3

Now try with signal - Example 3 - Write a program which sleep for long time use it as command in os.system() and then kill it by kill -15 or kill -9

os.system('command') #it returns signal num by which it is killed
15 in bits - 00000000 00001111
Signal num is 00001111 which means 15

You can have a python program as command = 'python command.py'

import sys
sys.exit(n)  # here n would be exit code

In case of c or c++ program you can use return from main() or exit(n) from any function #

Note - This is applicable on unix

On Unix, the return value is the exit status of the process encoded in the format specified for wait(). Note that POSIX does not specify the meaning of the return value of the C system() function, so the return value of the Python function is system-dependent.

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

.

Community
  • 1
  • 1
AlokThakur
  • 3,599
  • 1
  • 19
  • 32
  • Can you post any documentation or link which says this? – shane Nov 23 '16 at 06:54
  • 1
    @shane My answer is applicable for unix, I am not sure on windows, I have referred below - https://docs.python.org/2/library/os.html#os.system, which says it's return would be as per system call wait(), then I referred - https://docs.python.org/2/library/os.html#os.wait – AlokThakur Nov 24 '16 at 05:46
  • 5
    NB: You can get the return code with `os.WEXITSTATUS(os.system(my_call))`. So for example `sys.exit(os.WEXITSTATUS(os.system('exit 2')))` will exit with status code 2. – brandones Dec 09 '16 at 20:05
20

You might want to use

return_value = os.popen('ls').read()

instead. os.system only returns the error value.

The os.popen is a neater wrapper for subprocess.Popen function as is seen within the python source code.

user2589273
  • 2,379
  • 20
  • 29
  • 1
    Another crazy alternative to the clearly spelled out guidance in the documentation for `os.system`: use `subprocess` instead. – tripleee Dec 23 '20 at 08:21
  • @triplee I think that if you look at the os.popen function in the actual python code (https://github.com/python/cpython/blob/master/Lib/os.py) you will find it uses subprocess.Popen anyway. – user2589273 Dec 26 '20 at 17:24
13

"On Unix, the return value is the exit status of the process encoded in the format specified for wait(). Note that POSIX does not specify the meaning of the return value of the C system() function, so the return value of the Python function is system-dependent."

http://docs.python.org/library/os.html#os.system

There is no error, so the exit code is zero

cEz
  • 4,932
  • 1
  • 25
  • 38
  • 1
    And the return code os os.wait() encodes both the return value and the signal that killed the process. See http://stackoverflow.com/a/7616227/496127 – pwan Jun 14 '12 at 19:23
5

os.system() returns some unix output, not the command output. So, if there is no error then exit code written as 0.

sam
  • 18,509
  • 24
  • 83
  • 116