https://github.com/python/cpython/commit/fe7717c6116402a05854e0d6ccb1016990f378b0
commit: fe7717c6116402a05854e0d6ccb1016990f378b0
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-09-25T11:34:05Z
summary:

gh-158080: Py_InitializeFromConfig() no longer exits Python (#158085)

If a command line option wants to exit Python, move this option
processing from PyConfig_Read() to Py_Main(). So
Py_InitializeFromInitConfig() and Py_InitializeFromConfig() can no
longer return an exit code.

Deprecate PyInitConfig_GetExitCode(), PyStatus_Exit(), and PyStatus_IsExit()
functions, and PyStatus.exitcode member.

Renumber getopt.c long options to start at 1, instead of 0.

files:
A Misc/NEWS.d/next/C_API/2026-09-24-15-27-35.gh-issue-158080.YIqypf.rst
M Doc/c-api/init_config.rst
M Doc/c-api/interp-lifecycle.rst
M Doc/whatsnew/3.16.rst
M Include/cpython/initconfig.h
M Include/internal/pycore_initconfig.h
M Lib/test/test_cmd_line.py
M Lib/test/test_embed.py
M Modules/main.c
M Programs/_bootstrap_python.c
M Programs/_testembed.c
M Python/getopt.c
M Python/initconfig.c
M Python/pylifecycle.c

diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst
index ef09639189a6c27..400a05758c95174 100644
--- a/Doc/c-api/init_config.rst
+++ b/Doc/c-api/init_config.rst
@@ -116,15 +116,14 @@ Error Handling
 
    Get the *config* exit code.
 
-   * Set *\*exitcode* and return ``1`` if *config* has an exit code set.
-   * Return ``0`` if *config* has no exit code set.
+   Return ``0`` and leave *\*exitcode* unchanged.
 
-   Only the ``Py_InitializeFromInitConfig()`` function can set an exit
-   code if the ``parse_argv`` option is non-zero.
+   In Python 3.15, :c:func:`Py_InitializeFromInitConfig` sets an exit code if a
+   command line option wants to exit Python. This is no longer the case in
+   Python 3.16. Instead, the option is now processed in :c:func:`Py_RunMain`.
+   This function became useless.
 
-   An exit code can be set when parsing the command line failed (exit
-   code ``2``) or when a command line option asks to display the command
-   line help (exit code ``0``).
+   .. deprecated:: next
 
 
 Get Options
@@ -247,10 +246,11 @@ Initialize Python
 
    * Return ``0`` on success.
    * Set an error in *config* and return ``-1`` on error.
-   * Set an exit code in *config* and return ``-1`` if Python wants to
-     exit.
 
-   See ``PyInitConfig_GetExitcode()`` for the exit code case.
+   .. versionchanged:: next
+      The function no longer sets an exit code if a command line option wants
+      to exit Python. Instead, the option is now processed in
+      :c:func:`Py_RunMain`.
 
 
 .. _pyinitconfig-opts:
@@ -690,9 +690,6 @@ Example of customized Python always running in isolated 
mode::
 
     exception:
         PyConfig_Clear(&config);
-        if (PyStatus_IsExit(status)) {
-            return status.exitcode;
-        }
         /* Display the error message and exit the process with
            non-zero exit code */
         Py_ExitStatusException(status);
@@ -758,6 +755,8 @@ PyStatus
 
       Exit code. Argument passed to ``exit()``.
 
+      .. deprecated:: next
+
    .. c:member:: const char *err_msg
 
       Error message.
@@ -788,6 +787,11 @@ PyStatus
 
       Exit Python with the specified exit code.
 
+      .. deprecated:: next
+         :c:func:`Py_InitializeFromConfig` no longer sets an exit code if a
+         command line option wants to exit Python. Instead, the option is
+         now processed in :c:func:`Py_RunMain`.
+
    Functions to handle a status:
 
    .. c:function:: int PyStatus_Exception(PyStatus status)
@@ -803,6 +807,11 @@ PyStatus
 
       Is the result an exit?
 
+      .. deprecated:: next
+         :c:func:`Py_InitializeFromConfig` no longer sets an exit code if a
+         command line option wants to exit Python. Instead, the option is
+         now processed in :c:func:`Py_RunMain`.
+
    .. c:function:: void Py_ExitStatusException(PyStatus status)
 
       Call ``exit(exitcode)`` if *status* is an exit. Print the error
diff --git a/Doc/c-api/interp-lifecycle.rst b/Doc/c-api/interp-lifecycle.rst
index bd4125cacdd0e66..efd208263bdf339 100644
--- a/Doc/c-api/interp-lifecycle.rst
+++ b/Doc/c-api/interp-lifecycle.rst
@@ -127,6 +127,11 @@ Initializing and finalizing the interpreter
    interpreter, populating the runtime configuration structure, and querying
    the returned status structure.
 
+   .. versionchanged:: next
+      The function no longer returns an exit code if a command line option
+      wants to exit Python. Instead, the option is processed in
+      :c:func:`Py_RunMain`.
+
 
 .. c:function:: int Py_IsInitialized()
 
diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst
index 3d3125ad17b126b..7a1f9410c87fc7d 100644
--- a/Doc/whatsnew/3.16.rst
+++ b/Doc/whatsnew/3.16.rst
@@ -1128,6 +1128,14 @@ Deprecated C APIs
   and :c:func:`PyAsyncGen_New` are deprecated.
   They are scheduled for removal in 3.18.
 
+* Deprecate :c:func:`PyInitConfig_GetExitCode`, :c:func:`PyStatus_Exit`,
+  and :c:func:`PyStatus_IsExit` functions, and :c:member:`PyStatus.exitcode`
+  member. :c:func:`Py_InitializeFromInitConfig` and
+  :c:func:`Py_InitializeFromConfig` can no longer return an exit code.
+  Instead, if a command line option wants to exit Python, the option is
+  now processed in :c:func:`Py_RunMain`.
+  (Contributed by Victor Stinner in :gh:`158080`.)
+
 * :c:func:`PyModule_GetFilename` is no longer deprecated, but using
   :c:func:`PyModule_GetFilenameObject` instead is still recommended.
   (Contributed by Victor Stinner in :gh:`154757`.)
diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h
index 1ccc496c63ac780..846e05fb26a4d83 100644
--- a/Include/cpython/initconfig.h
+++ b/Include/cpython/initconfig.h
@@ -11,19 +11,19 @@ typedef struct {
     enum {
         _PyStatus_TYPE_OK=0,
         _PyStatus_TYPE_ERROR=1,
-        _PyStatus_TYPE_EXIT=2
+        _PyStatus_TYPE_EXIT=2  // deprecated
     } _type;
     const char *func;
     const char *err_msg;
-    int exitcode;
+    Py_DEPRECATED(3.16) int exitcode;
 } PyStatus;
 
 PyAPI_FUNC(PyStatus) PyStatus_Ok(void);
 PyAPI_FUNC(PyStatus) PyStatus_Error(const char *err_msg);
 PyAPI_FUNC(PyStatus) PyStatus_NoMemory(void);
-PyAPI_FUNC(PyStatus) PyStatus_Exit(int exitcode);
+Py_DEPRECATED(3.16) PyAPI_FUNC(PyStatus) PyStatus_Exit(int exitcode);
 PyAPI_FUNC(int) PyStatus_IsError(PyStatus err);
-PyAPI_FUNC(int) PyStatus_IsExit(PyStatus err);
+Py_DEPRECATED(3.16) PyAPI_FUNC(int) PyStatus_IsExit(PyStatus err);
 PyAPI_FUNC(int) PyStatus_Exception(PyStatus err);
 
 /* --- PyWideStringList ------------------------------------------------ */
@@ -242,6 +242,11 @@ typedef struct PyConfig {
     // PYTHON_PRESITE=package.module or -X presite=package.module
     wchar_t *run_presite;
 #endif
+
+    // If a command line option wants to exit Python, store it in this member
+    // and only process the option in Py_RunMain() instead of PyConfig_Read().
+    // If equals to 0, there is no option.
+    int _deferred_cmdline_option;
 } PyConfig;
 
 PyAPI_FUNC(void) PyConfig_InitPythonConfig(PyConfig *config);
@@ -293,7 +298,7 @@ PyAPI_FUNC(void) PyInitConfig_Free(PyInitConfig *config);
 
 PyAPI_FUNC(int) PyInitConfig_GetError(PyInitConfig* config,
     const char **err_msg);
-PyAPI_FUNC(int) PyInitConfig_GetExitCode(PyInitConfig* config,
+Py_DEPRECATED(3.16) PyAPI_FUNC(int) PyInitConfig_GetExitCode(PyInitConfig* 
config,
     int *exitcode);
 
 PyAPI_FUNC(int) PyInitConfig_HasOption(PyInitConfig *config,
diff --git a/Include/internal/pycore_initconfig.h 
b/Include/internal/pycore_initconfig.h
index 183b2d45c5ede1c..50df2efdd4e5269 100644
--- a/Include/internal/pycore_initconfig.h
+++ b/Include/internal/pycore_initconfig.h
@@ -182,6 +182,8 @@ extern PyObject* _PyConfig_CreateXOptionsDict(const 
PyConfig *config);
 
 extern void _Py_DumpPathConfig(PyThreadState *tstate);
 
+extern int _PyConfig_ProcessDeferredCmdlineOption(PyConfig *config);
+
 
 /* --- Function used for testing ---------------------------------- */
 
diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py
index 4c1abb15c0cb148..476a481a0ba54b3 100644
--- a/Lib/test/test_cmd_line.py
+++ b/Lib/test/test_cmd_line.py
@@ -133,11 +133,16 @@ def test_site_flag(self):
 
     @support.cpython_only
     def test_version(self):
-        version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii")
-        for switch in '-V', '--version', '-VV':
-            rc, out, err = assert_python_ok(switch)
-            self.assertNotStartsWith(err, version)
-            self.assertStartsWith(out, version)
+        short_version = ('Python %d.%d' % sys.version_info[:2])
+        for switch in ('-V', '--version'):
+            with self.subTest(switch=switch):
+                rc, out, err = assert_python_ok(switch)
+                self.assertStartsWith(out, short_version.encode())
+                self.assertEqual(err, b'')
+
+        rc, out, err = assert_python_ok('-VV')
+        self.assertEqual(out.rstrip(), f"Python {sys.version}".encode())
+        self.assertEqual(err, b'')
 
     def test_verbose(self):
         # -v causes imports to write to stderr.  If the write to
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index 77b231323cc2757..39485afcdb0f57d 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -783,6 +783,7 @@ class InitConfigTests(EmbeddingTestsMixin, 
unittest.TestCase):
         'use_frozen_modules': not support.Py_DEBUG,
         'safe_path': False,
         '_is_python_build': IGNORE_CONFIG,
+        '_deferred_cmdline_option': 0,
     }
     if Py_STATS:
         CONFIG_COMPAT['_pystats'] = False
diff --git 
a/Misc/NEWS.d/next/C_API/2026-09-24-15-27-35.gh-issue-158080.YIqypf.rst 
b/Misc/NEWS.d/next/C_API/2026-09-24-15-27-35.gh-issue-158080.YIqypf.rst
new file mode 100644
index 000000000000000..4413b328d474e48
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2026-09-24-15-27-35.gh-issue-158080.YIqypf.rst
@@ -0,0 +1,6 @@
+Deprecate :c:func:`PyInitConfig_GetExitCode`, :c:func:`PyStatus_Exit`, and
+:c:func:`PyStatus_IsExit` functions, and :c:member:`PyStatus.exitcode`
+member. :c:func:`Py_InitializeFromInitConfig` and
+:c:func:`Py_InitializeFromConfig` can no longer return an exit code.
+Instead, if a command line option wants to exit Python, the option is
+now processed in :c:func:`Py_RunMain`. Patch by Victor Stinner.
diff --git a/Modules/main.c b/Modules/main.c
index ef22331760906ce..44a025d500e35e2 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -749,13 +749,21 @@ pymain_set_path0(PyObject *main_importer_path)
 static void
 pymain_run_python(int *exitcode)
 {
-    int set_running_main = 0;
-
-    PyObject *main_importer_path = NULL;
     PyInterpreterState *interp = _PyInterpreterState_GET();
     /* pymain_repl() and pymain_run_stdin() modify the config */
     PyConfig *config = (PyConfig*)_PyInterpreterState_GetConfig(interp);
 
+    // Process command line options which want to exit Python
+    int cmdline_exitcode = _PyConfig_ProcessDeferredCmdlineOption(config);
+    if (cmdline_exitcode >= 0) {
+        *exitcode = cmdline_exitcode;
+        return;
+    }
+
+    int set_running_main = 0;
+
+    PyObject *main_importer_path = NULL;
+
     /* ensure path config is written into global variables */
     PyStatus status = _PyPathConfig_UpdateGlobal(config);
     if (_PyStatus_EXCEPTION(status)) {
@@ -910,10 +918,7 @@ static int
 pymain_main(_PyArgv *args)
 {
     PyStatus status = pymain_init(args);
-    if (_PyStatus_IS_EXIT(status)) {
-        pymain_free();
-        return status.exitcode;
-    }
+    assert(!_PyStatus_IS_EXIT(status));
     if (_PyStatus_EXCEPTION(status)) {
         pymain_exit_error(status);
     }
diff --git a/Programs/_bootstrap_python.c b/Programs/_bootstrap_python.c
index d30ef8c879d8153..c65d616afbd5010 100644
--- a/Programs/_bootstrap_python.c
+++ b/Programs/_bootstrap_python.c
@@ -104,9 +104,6 @@ main(int argc, char **argv)
 
 error:
     PyConfig_Clear(&config);
-    if (PyStatus_IsExit(status)) {
-        return status.exitcode;
-    }
     Py_ExitStatusException(status);
 }
 
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
index 79e817829c15947..592c23756201f01 100644
--- a/Programs/_testembed.c
+++ b/Programs/_testembed.c
@@ -1722,7 +1722,7 @@ static int test_initconfig_api(void)
         goto error;
     }
 
-    // Set a list of UTF-8 strings (argv)
+    // Set a list of UTF-8 strings (xoptions)
     char* xoptions[] = {"faulthandler"};
     if (PyInitConfig_SetStrList(config, "xoptions",
                                 Py_ARRAY_LENGTH(xoptions), xoptions) < 0) {
@@ -1814,29 +1814,25 @@ static int test_initconfig_get_api(void)
 
 static int test_initconfig_exit(void)
 {
+    // -h command line option is stored as PyConfig._deferred_cmdline_option
     PyInitConfig *config = PyInitConfig_Create();
     if (config == NULL) {
         printf("Init allocation error\n");
         return 1;
     }
 
-    char *argv[] = {PROGRAM_NAME_UTF8, "--help"};
+    char *argv[] = {PROGRAM_NAME_UTF8, "-h"};
     assert(PyInitConfig_SetStrList(config, "argv",
                                    Py_ARRAY_LENGTH(argv), argv) == 0);
-
     assert(PyInitConfig_SetInt(config, "parse_argv", 1) == 0);
 
-    assert(Py_InitializeFromInitConfig(config) < 0);
-
-    int exitcode;
-    assert(PyInitConfig_GetExitCode(config, &exitcode) == 1);
-    assert(exitcode == 0);
+    assert(Py_InitializeFromInitConfig(config) == 0);
+    PyInitConfig_Free(config);
 
-    const char *err_msg;
-    assert(PyInitConfig_GetError(config, &err_msg) == 1);
-    assert(strcmp(err_msg, "exit code 0") == 0);
+    const PyConfig *rt_config = _Py_GetConfig();
+    assert(rt_config->_deferred_cmdline_option == 'h');
 
-    PyInitConfig_Free(config);
+    Py_Finalize();
     return 0;
 }
 
diff --git a/Python/getopt.c b/Python/getopt.c
index 79bea2359ffffcf..7e918189c716a9e 100644
--- a/Python/getopt.c
+++ b/Python/getopt.c
@@ -41,10 +41,10 @@ static const wchar_t *opt_ptr = L"";
 
 static const _PyOS_LongOption longopts[] = {
     /* name, has_arg, val (used in switch in initconfig.c) */
-    {L"check-hash-based-pycs", 1, 0},
-    {L"help-all", 0, 1},
-    {L"help-env", 0, 2},
-    {L"help-xoptions", 0, 3},
+    {L"check-hash-based-pycs", 1, 1},
+    {L"help-all", 0, 2},
+    {L"help-env", 0, 3},
+    {L"help-xoptions", 0, 4},
     {NULL, 0, -1},                     /* sentinel */
 };
 
diff --git a/Python/initconfig.c b/Python/initconfig.c
index d683fdd6abc6e1b..6de12db9d600ecc 100644
--- a/Python/initconfig.c
+++ b/Python/initconfig.c
@@ -204,6 +204,7 @@ static const PyConfigSpec PYCONFIG_SPEC[] = {
     SPEC(module_search_paths_set, BOOL, INIT_ONLY, NO_SYS),
     SPEC(pythonpath_env, WSTR_OPT, INIT_ONLY, NO_SYS),
     SPEC(sys_path_0, WSTR_OPT, INIT_ONLY, NO_SYS),
+    SPEC(_deferred_cmdline_option, INT, INIT_ONLY, NO_SYS),
 
     // Array terminator
     {NULL, 0, 0, 0, NO_SYS},
@@ -2996,13 +2997,17 @@ static PyStatus
 config_parse_cmdline(PyConfig *config, PyWideStringList *warnoptions,
                      Py_ssize_t *opt_index)
 {
+    // Only store the first option
+#define DEFER_OPTION(OPTION) \
+        do { \
+            if (config->_deferred_cmdline_option == 0) { \
+                config->_deferred_cmdline_option = (OPTION); \
+            } \
+        } while (0)
+
     PyStatus status;
     const PyWideStringList *argv = &config->argv;
     int print_version = 0;
-    const wchar_t* program = config->program_name;
-    if (!program && argv->length >= 1) {
-        program = argv->items[0];
-    }
 
     _PyOS_ResetGetOpt();
     do {
@@ -3045,7 +3050,7 @@ config_parse_cmdline(PyConfig *config, PyWideStringList 
*warnoptions,
 
         switch (c) {
         // Integers represent long options, see Python/getopt.c
-        case 0:
+        case 1:
             // check-hash-based-pycs
             if (wcscmp(_PyOS_optarg, L"always") == 0
                 || wcscmp(_PyOS_optarg, L"never") == 0
@@ -3057,27 +3062,24 @@ config_parse_cmdline(PyConfig *config, PyWideStringList 
*warnoptions,
                     return status;
                 }
             } else {
-                fprintf(stderr, "--check-hash-based-pycs must be one of "
-                        "'default', 'always', or 'never'\n");
-                config_usage(1, program);
-                return _PyStatus_EXIT(2);
+                DEFER_OPTION(c);
             }
             break;
 
-        case 1:
+        case 2:
             // help-all
-            config_complete_usage(program);
-            return _PyStatus_EXIT(0);
+            DEFER_OPTION(c);
+            break;
 
-        case 2:
+        case 3:
             // help-env
-            config_envvars_usage();
-            return _PyStatus_EXIT(0);
+            DEFER_OPTION(c);
+            break;
 
-        case 3:
+        case 4:
             // help-xoptions
-            config_xoptions_usage();
-            return _PyStatus_EXIT(0);
+            DEFER_OPTION(c);
+            break;
 
         case 'b':
             config->bytes_warning++;
@@ -3136,8 +3138,8 @@ config_parse_cmdline(PyConfig *config, PyWideStringList 
*warnoptions,
 
         case 'h':
         case '?':
-            config_usage(0, program);
-            return _PyStatus_EXIT(0);
+            DEFER_OPTION(c);
+            break;
 
         case 'V':
             print_version++;
@@ -3162,15 +3164,16 @@ config_parse_cmdline(PyConfig *config, PyWideStringList 
*warnoptions,
 
         default:
             /* unknown argument: parsing failed */
-            config_usage(1, program);
-            return _PyStatus_EXIT(2);
+            DEFER_OPTION(c);
+            break;
         }
-    } while (1);
+    } while (config->_deferred_cmdline_option == 0);
 
-    if (print_version) {
-        printf("Python %s\n",
-                (print_version >= 2) ? Py_GetVersion() : PY_VERSION);
-        return _PyStatus_EXIT(0);
+    if (print_version >= 2) {
+        DEFER_OPTION('W');
+    }
+    else if (print_version >= 1) {
+        DEFER_OPTION('V');
     }
 
     if (config->run_command == NULL && config->run_module == NULL
@@ -3192,6 +3195,72 @@ config_parse_cmdline(PyConfig *config, PyWideStringList 
*warnoptions,
     *opt_index = _PyOS_optind;
 
     return _PyStatus_OK();
+
+#undef DEFER_OPTION
+}
+
+
+int
+_PyConfig_ProcessDeferredCmdlineOption(PyConfig *config)
+{
+    int c = config->_deferred_cmdline_option;
+    config->_deferred_cmdline_option = 0;
+    if (c == 0) {
+        // There is no deferred option
+        return -1;
+    }
+
+    // Select the program name
+    const PyWideStringList *argv = &config->argv;
+    const wchar_t* program = config->program_name;
+    if (!program && argv->length >= 1) {
+        program = argv->items[0];
+    }
+    if (!program) {
+        program = L"python";
+    }
+
+    switch (c) {
+    case 'h':
+    case '?':
+        config_usage(0, program);
+        return 0;
+
+    case 'V':
+        printf("Python %s\n", PY_VERSION);
+        return 0;
+
+    case 'W':  // -VV or more -V options
+        printf("Python %s\n", Py_GetVersion());
+        return 0;
+
+    // Integers represent long options, see Python/getopt.c
+    case 1:
+        // check-hash-based-pycs
+        fprintf(stderr, "--check-hash-based-pycs must be one of "
+                "'default', 'always', or 'never'\n");
+        config_usage(1, program);
+        return 2;
+
+    case 2:
+        // help-all
+        config_complete_usage(program);
+        return 0;
+
+    case 3:
+        // help-env
+        config_envvars_usage();
+        return 0;
+
+    case 4:
+        // help-xoptions
+        config_xoptions_usage();
+        return 0;
+
+    default:
+        config_usage(1, program);
+        return 2;
+    }
 }
 
 
@@ -3634,7 +3703,6 @@ config_argv0_add_exe(PyConfig *config)
 
    * Command line arguments
    * Environment variables
-   * Py_xxx global configuration variables
 
    The only side effects are to modify config and to call _Py_SetArgcArgv(). */
 PyStatus
@@ -3966,22 +4034,7 @@ PyInitConfig_Free(PyInitConfig *config)
 int
 PyInitConfig_GetError(PyInitConfig* config, const char **perr_msg)
 {
-    if (_PyStatus_IS_EXIT(config->status)) {
-        char buffer[22];  // len("exit code -2147483648\0")
-        PyOS_snprintf(buffer, sizeof(buffer),
-                      "exit code %i",
-                      config->status.exitcode);
-
-        if (config->err_msg != NULL) {
-            free(config->err_msg);
-        }
-        config->err_msg = strdup(buffer);
-        if (config->err_msg != NULL) {
-            *perr_msg = config->err_msg;
-            return 1;
-        }
-        config->status = _PyStatus_NO_MEMORY();
-    }
+    assert(!_PyStatus_IS_EXIT(config->status));
 
     if (_PyStatus_IS_ERROR(config->status) && config->status.err_msg != NULL) {
         *perr_msg = config->status.err_msg;
@@ -3997,13 +4050,8 @@ PyInitConfig_GetError(PyInitConfig* config, const char 
**perr_msg)
 int
 PyInitConfig_GetExitCode(PyInitConfig* config, int *exitcode)
 {
-    if (_PyStatus_IS_EXIT(config->status)) {
-        *exitcode = config->status.exitcode;
-        return 1;
-    }
-    else {
-        return 0;
-    }
+    assert(!_PyStatus_IS_EXIT(config->status));
+    return 0;
 }
 
 
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index a9c98d73fd0f721..8888f523559123a 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -3830,10 +3830,9 @@ _Py_FatalRefcountErrorFunc(const char *func, const char 
*msg)
 void _Py_NO_RETURN
 Py_ExitStatusException(PyStatus status)
 {
-    if (_PyStatus_IS_EXIT(status)) {
-        exit(status.exitcode);
-    }
-    else if (_PyStatus_IS_ERROR(status)) {
+    assert(!_PyStatus_IS_EXIT(status));
+
+    if (_PyStatus_IS_ERROR(status)) {
         fatal_error(fileno(stderr), 1, status.func, status.err_msg, 1);
     }
     else {

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to