Skip to content

Fix #15132: preserve sys.exit() exit codes in non-interactive mode - #15367

Open
MsfPablo wants to merge 1 commit into
ipython:mainfrom
MsfPablo:fix-15132
Open

Fix #15132: preserve sys.exit() exit codes in non-interactive mode#15367
MsfPablo wants to merge 1 commit into
ipython:mainfrom
MsfPablo:fix-15132

Conversation

@MsfPablo

Copy link
Copy Markdown

Fixes #15132

When running ipython -c "import sys;sys.exit(N)" or executing a script via ipython script.py that calls sys.exit(N), IPython returned exit code 1 instead of the value passed to sys.exit(). The exit code was hardcoded in two places:

  • IPython/terminal/ipapp.pyTerminalIPythonApp.start() called sys.exit(1) whenever the last execution failed, regardless of whether the failure was a SystemExit raised by user code.
  • IPython/core/shellapp.py_run_cmd_line_code() had the same hardcoded self.exit(1) for file execution errors.

This change extracts the original exit code from the SystemExit exception that InteractiveShell stores on last_execution_result.error_in_exec (and that _exec_file raises in the file path), and propagates it to the process exit. Exit code 1 is preserved only for genuine execution failures that aren't SystemExit.

Behavior:

  • sys.exit(0) / sys.exit() → exit code 0
  • sys.exit(N) for any integer N → preserves N
  • Non-SystemExit execution failures → exit code 1 (unchanged)
  • SystemExit in script file path → exits quietly, no traceback

AI disclosure

This PR was authored with assistance from Claude (Anthropic). The implementation, tests, and review were AI-assisted.

Co-Authored-By: Claude noreply@anthropic.com

…mode

When running `ipython -c "import sys;sys.exit(N)"` or
`ipython script.py` (with a script that calls sys.exit(N)), IPython
returned exit code 1 instead of the value passed to sys.exit(). The
exit code was hardcoded in TerminalIPythonApp.start() and the file
execution branch of InteractiveShellApp._run_cmd_line_code().

Extract the original exit code from the SystemExit exception stored on
the shell's last_execution_result and propagate it; default to 1 only
for genuine execution failures. Handle SystemExit before the bare
except: in the file execution path so it exits quietly (without a
traceback), matching Python's own behavior.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ipython turns all non-zero exit codes to 1 when script ran with "ipython -c script.py" uses sys.exit()

1 participant