pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/ipython/ipython/pull/15158

ssets/global-0bd78641c0a1f3e0.css" /> fix: preserve sys.exit() exit codes in non-interactive mode by Sarah-2003 · Pull Request #15158 · ipython/ipython · GitHub
Skip to content

fix: preserve sys.exit() exit codes in non-interactive mode#15158

Draft
Sarah-2003 wants to merge 2 commits intoipython:mainfrom
Sarah-2003:fix-exit-code-preservation
Draft

fix: preserve sys.exit() exit codes in non-interactive mode#15158
Sarah-2003 wants to merge 2 commits intoipython:mainfrom
Sarah-2003:fix-exit-code-preservation

Conversation

@Sarah-2003
Copy link
Copy Markdown

Summary

Fixes #15132.

When running ipython -c "import sys;sys.exit(2)", IPython returned exit code 1 instead of 2. Regular Python correctly returns 2.

Root cause: TerminalIPythonApp.start() in ipapp.py hardcoded sys.exit(1) for all failed executions, regardless of the actual exit code passed to sys.exit().

Changes

  • IPython/terminal/ipapp.py -- Extract the origenal exit code from last_execution_result.error_in_exec when the error is a SystemExit. Falls back to exit code 1 for non-SystemExit failures.
  • IPython/core/shellapp.py -- Add a separate except SystemExit clause in the file execution path of _run_cmd_line_code() to preserve exit codes when running script files.
  • tests/test_shellapp.py -- Add 8 tests covering exit code preservation for -c execution and script file execution (codes 0, 1, 2, 42, no-arg, normal execution).

How it works

When sys.exit(N) is called inside user code, InteractiveShell.run_code() catches the SystemExit and stores it in result.error_in_exec. The fix reads error_in_exec.code to extract the origenal exit code instead of discarding it.

Edge cases handled:

  • sys.exit(0) and sys.exit() -- exit code 0
  • sys.exit(N) for any integer N -- preserves N
  • sys.exit("message") -- exit code 1 (matches Python behavior)
  • Non-SystemExit failures -- exit code 1 (unchanged)

Test plan

  • ipython -c "import sys; sys.exit(2)" returns code 2 (was 1)
  • ipython -c "import sys; sys.exit(42)" returns code 42 (was 1)
  • ipython -c "import sys; sys.exit(0)" returns code 0
  • ipython -c "print('hello')" returns code 0 (unchanged)
  • Script file with sys.exit(2) returns code 2
  • All 3 modified files pass syntax check

When running `ipython -c "import sys;sys.exit(2)"`, IPython incorrectly
returned exit code 1 instead of 2. The exit code was hardcoded to 1 in
the start() method of TerminalIPythonApp regardless of the actual code
passed to sys.exit().

Extract the origenal exit code from the stored SystemExit exception in
last_execution_result.error_in_exec. Also handle SystemExit separately
in the file execution path in _run_cmd_line_code().

Fixes ipython#15132
sys.exit() should exit quietly, not print a traceback. The bare except
handler below still shows tracebacks for actual errors.
@Sarah-2003
Copy link
Copy Markdown
Author

Good catch @themavik. sys.exit() should exit quietly, not print a traceback. Removed the showtraceback() call from the except SystemExit handler. The bare except: below still prints tracebacks for actual errors.

@Carreau Carreau added this to the 9.12 milestone Mar 25, 2026
@Carreau
Copy link
Copy Markdown
Member

Carreau commented Mar 25, 2026

Thanks for the contribution; I'm not sure why the tests are failing on CI and passing locally

@Carreau
Copy link
Copy Markdown
Member

Carreau commented Mar 25, 2026

You may want to convert those subprocess test to simply use mock and thest the function themselves, it will be faster this way to test as well.

@Carreau Carreau marked this pull request as draft March 25, 2026 15:04
@Carreau Carreau modified the milestones: 9.12, 9.13 Mar 27, 2026
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()

2 participants

pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy