322

I got a message saying script xyz.py returned exit code 0. What does this mean?

What do the exit codes in Python mean? How many are there? Which ones are important?

Teun Zengerink
  • 4,277
  • 5
  • 30
  • 32
sundeep
  • 4,048
  • 7
  • 25
  • 22

16 Answers16

320

You're looking for calls to sys.exit() (exit() calls sys.exit()) in the script. The argument to that method is returned to the environment as the exit code.

It's fairly likely that the script is never calling the exit method, and that 0 is the default exit code.

KaiLando
  • 23
  • 7
Dave Costa
  • 47,262
  • 8
  • 56
  • 72
  • 14
    Not sure at all. In Unix/Linux, the standard is: exit 0 in the case everything was ok. Type a command, then echo $?: if you read 0, it returned without an error. The idea is to have standard tests. If the code xyz.py did not encounter any error, it SHOULD return 0! – Bruno von Paris Oct 15 '12 at 09:20
  • 2
    If you would like to change the exit code, prefer to exit cleanly using the exit builtin, see [this answer](http://stackoverflow.com/a/42719261/363437) – vidstige Mar 10 '17 at 13:14
  • @vidstige: The `exit()` "built-in" (it's not actually a built-in all the time; e.g. it won't exist when Python is run with the `-S` switch) is the *wrong* solution; you want `sys.exit()` (which does in fact exit cleanly/consistently), not `exit()` (which is allowed to be replaced with weird things by tools, where `sys.exit` is generally supposed to stay untouched). The "unclean exit" function is `os._exit()`, which does terminate abruptly (it's used largely to kill workers in `fork`-based `multiprocessing` scenarios to avoid invoking cleanup that the parent process set up before the `fork`). – ShadowRanger Dec 02 '20 at 14:19
137

From the documentation for sys.exit:

The optional argument arg can be an integer giving the exit status (defaulting to zero), or another type of object. If it is an integer, zero is considered “successful termination” and any nonzero value is considered “abnormal termination” by shells and the like. Most systems require it to be in the range 0-127, and produce undefined results otherwise. Some systems have a convention for assigning specific meanings to specific exit codes, but these are generally underdeveloped; Unix programs generally use 2 for command line syntax errors and 1 for all other kind of errors.

One example where exit codes are used are in shell scripts. In Bash you can check the special variable $? for the last exit status:

me@mini:~$ python -c ""; echo $?
0
me@mini:~$ python -c "import sys; sys.exit(0)"; echo $?
0
me@mini:~$ python -c "import sys; sys.exit(43)"; echo $?
43

Personally I try to use the exit codes I find in /usr/include/asm-generic/errno.h (on a Linux system), but I don't know if this is the right thing to do.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Eigir
  • 1,969
  • 2
  • 14
  • 19
  • 4
    From another post I found this link: http://tldp.org/LDP/abs/html/exitcodes.html Might be usefull. :) – Eigir Nov 20 '08 at 11:10
  • 11
    errno.h is typically for function call exit codes. Attempts to standardize program exit codes have resulted in /usr/include/sysexits.h being present on most POSIX systems. – mpounsett Jan 10 '12 at 02:43
  • 2
    It's very good to know that "Unix programs generally use 2 for command line syntax errors"! – dantiston Mar 18 '15 at 23:34
  • 4
    @dantiston **Concur.** Die-hard dyed-in-the-wool Gentoo advocate, yet I never knew that... until this fated day. (_My shame ends now._) Relatedly, note that `grep` breaks this trend by exiting with `1` when no lines match and `2` on actual errors. Thanks alot, Stallman. – Cecil Curry Jan 03 '16 at 08:57
51

For the record, you can use POSIX standard exit codes defined here.

Example:

import sys, os

try:
    config()
except:
    sys.exit(os.EX_CONFIG) 
try:
    do_stuff()
except:
    sys.exit(os.EX_SOFTWARE)
sys.exit(os.EX_OK) # code 0, all ok
laffuste
  • 16,287
  • 8
  • 84
  • 91
  • 7
    According to the [docs](https://docs.python.org/3/library/os.html#process-management) these are only available on Unix operating systems so it is not fully portable. – phoenix Jun 09 '16 at 00:47
  • 2
    If you'd like portable POSIX codes that are available on all operating systems, see the [`exitstatus`](https://pypi.org/project/exitstatus/) PyPI package. – phoenix Jul 23 '18 at 18:39
  • 16
    The entirety of that package is 0 for success, and 1 for failure. – Pavel Minaev Sep 09 '19 at 22:20
  • 6
    I thought you were kidding, Pavel. You were in fact not kidding: https://github.com/johnthagen/exitstatus/blob/master/exitstatus.py – rud Jan 06 '22 at 12:05
23

There is an errno module that defines standard exit codes:

For example, Permission denied is error code 13:

import errno, sys

if can_access_resource():
    do_something()
else:
    sys.exit(errno.EACCES)
Asclepius
  • 57,944
  • 17
  • 167
  • 143
Oli
  • 15,345
  • 8
  • 30
  • 36
  • 47
    This is incorrect. These errno are not intended to be used as process exit codes. These are low level error codes intended to be used internally in programs, specifically those written in the C language. For Python, use exceptions whenever possible. – SvdB Aug 08 '14 at 17:11
  • 3
    You're right. These are to be used internally. But you do not normally raise exceptions at the end user level. You use sys.exit(x) with x being an integer you choose arbitrarily. But you can use those begining with EX_ and defined in 'os' module. Like os.EX_OK or os.EX_IOERR – Oli Aug 12 '14 at 08:50
  • 5
    Sorry, but I’m also down-voting this because it’s misleading. Exit status codes and error numbers are _not_ interchangable/complementary. Using the given example, “permission denied” has an _error code_ of 13 (according to `errno` and [errno.h](https://github.com/freebsd/freebsd/blob/master/sys/sys/errno.h#L51-L188)), but an _exit status code_ of 77 (according to `os` and [sysexits.h](https://github.com/freebsd/freebsd/blob/master/include/sysexits.h#L96-L116)). Programs that emit the former are non-standard (_de facto vel jure_) and won’t play nicely with others that rightly expect the latter. – Mark G. Jan 09 '20 at 18:44
18

Exit codes of 0 usually mean, "nothing wrong here." However if the programmer of the script didn't follow convention you may have to consult the source to see what it means. Usually a non-zero value is returned as an error code.

Sam Corder
  • 5,374
  • 3
  • 25
  • 30
14

The answer is "Depends on what exit code zero means".

However, in most cases, this means "Everything is Ok".


I like POSIX:

So, in the shell, I would type:

python script.py && echo 'OK' || echo 'Not OK'

If my Python script calls sys.exit(0), the shell returns 'OK'

If my Python script calls sys.exit(1) (or any non-zero integer), the shell returns 'Not OK'.

It's your job to get clever with the shell, and read the documentation (or the source) for your script to see what the exit codes mean.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
FlipMcF
  • 12,636
  • 2
  • 35
  • 44
14

Following Unix exit codes 0 - for success / OK, 1 - non success / error. You could simply use exit(0) or exit(1) call without importing sys module.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Lukasz Dynowski
  • 11,169
  • 9
  • 81
  • 124
  • 5
    exit is intended for the interactive shell. sys.exit is intended for scripts. See also this answer: https://stackoverflow.com/a/6501134/1144204 – highvelcty Oct 29 '21 at 19:21
8

If you would like to portably use the standard POSIX exit codes, see the exitstatus package on PyPI.

Install the package:

$ pip install exitstatus

Use in your code:

import sys
from exitstatus import ExitStatus

sys.exit(ExitStatus.success)
phoenix
  • 7,988
  • 6
  • 39
  • 45
6

The exit codes only have meaning as assigned by the script author. The Unix tradition is that exit code 0 means 'success', anything else is failure. The only way to be sure what the exit codes for a given script mean is to examine the script itself.

Harper Shelby
  • 16,475
  • 2
  • 44
  • 51
6

Operating system commands have exit codes. Look for Linux exit codes to see some material on this. The shell uses the exit codes to decide if the program worked, had problems, or failed. There are some efforts to create standard (or at least commonly-used) exit codes. See this Advanced Shell Script posting.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
S.Lott
  • 384,516
  • 81
  • 508
  • 779
6

I recommend a clean shutdown with the exit(0) builtin rather than using sys.exit()

I'm not sure if this is good advice.

The very documentation mentioned reads:

The site module (which is imported automatically during startup, except if the -S command-line option is given) adds several constants to the built-in namespace. They are useful for the interactive interpreter shell and should not be used in programs.

Then:

exit(code=None)

Objects that when printed, print a message like “Use quit() or Ctrl-D (i.e. EOF) to exit”, and when called, raise SystemExit with the specified exit code.

If we compare it to sys.exit() documentation, it's using the same mechanism which is raising a SystemExit exception.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
weakcamel
  • 81
  • 1
  • 4
3

Exit codes in many programming languages are up to programmers. So you have to look at your program source code (or manual). Zero usually means "everything went fine".

Davide
  • 17,098
  • 11
  • 52
  • 68
0

WORKAROUND: To face the bug in gitlab-ci (https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27668), I simply generated a file with the error code:

Python part:

with open("error_code.log", 'w') as file:
   file.write('2') # this will trigger a warning

and then in the yml file:

.step_name:
  variables:
    # my vars
  script:
    - python my_code.py arg1 arg2
    - exit `cat error_code.log`
  allow_failure:
    exit_codes:
      - 2
0

To Exit anywhere from python code you can right sys.exit()

This is called making normal termination, Use cases: a) Wrong password b) Wrong API Key c) Exception occurred, etc.

Code sample:

import sys; sys.exit()

Glauco
  • 1,385
  • 2
  • 10
  • 20
Yugal
  • 21
  • 6
0

script program.py returned error code 0 means that program.py doesn't have any errors. Just input your number that you got into os.strerror() to convert it into a message.

KaiLando
  • 23
  • 7
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 01 '23 at 21:05
-3

To allow exception handlers and other things execute I recommend a clean shutdown with the exit(0) builtin rather than using sys.exit() which terminates the process abruptly.

vidstige
  • 12,492
  • 9
  • 66
  • 110
  • 1
    So what;s the difference? Where does this information come from? Do you mean the execution of the "at exit" handlers or what exactly are you referring to? `SystemExit` appears to get raised either way. – 0xC0000022L Nov 20 '17 at 14:53
  • mm, I confused it with `os._exit`, the both seems to raise `SystemExit`. – vidstige Nov 20 '17 at 19:09
  • 3
    Wrong: `sys.exit()` **does** shutdown cleanly, just like `exit()`. They both do the _same_ thing: raise a `SystemExit` exception. Actually, `exit()` is meant for the interactive sessions, not scripts, so conceptually `sys.exit()` *is* the indicated one. You might be confusing with `os._exit()`, that's the one that terminates abruptly. – MestreLion Nov 05 '19 at 22:39
  • 1
    Adding to @MestreLion: `exit()` isn't even a true built-in; [it's jammed into the built-ins after the fact when the `site` module is imported](https://docs.python.org/3/library/constants.html#constants-added-by-the-site-module). This happens implicitly most of the time, but for Python scripts that are trying to run quickly, and don't rely on third-party modules (installed in `site-packages`), they can be run with the `-S` switch to disable import of `site` entirely, and `exit()` won't exist (`sys.exit()` still will). – ShadowRanger Dec 02 '20 at 14:41