From 969c9ce5608c824b4541d8874d70de24070720cb Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Sep 2026 21:43:00 +0200 Subject: [PATCH 1/5] gh-158001: Remove Py_SetProgramName() function Remove Py_SetProgramName(), Py_SetPythonHome(), PySys_SetArgv() and PySys_SetArgvEx() functions, deprecated since Python 3.11. --- Doc/c-api/interp-lifecycle.rst | 126 ------------------ Doc/data/refcounts.dat | 12 -- Doc/whatsnew/3.16.rst | 5 + Include/pylifecycle.h | 4 - Include/sysmodule.h | 3 - ...-09-23-21-45-43.gh-issue-158001.R_wX4E.rst | 3 + Programs/_testembed.c | 4 + Python/pathconfig.c | 6 +- Python/sysmodule.c | 9 +- 9 files changed, 20 insertions(+), 152 deletions(-) create mode 100644 Misc/NEWS.d/next/C_API/2026-09-23-21-45-43.gh-issue-158001.R_wX4E.rst diff --git a/Doc/c-api/interp-lifecycle.rst b/Doc/c-api/interp-lifecycle.rst index 46f5b1dd33963c..e2b73d3814c6d4 100644 --- a/Doc/c-api/interp-lifecycle.rst +++ b/Doc/c-api/interp-lifecycle.rst @@ -37,8 +37,6 @@ The following functions can be safely called before Python is initialized: * :c:func:`PyMem_SetAllocator` * :c:func:`PyMem_SetupDebugHooks` * :c:func:`PyObject_SetArenaAllocator` - * :c:func:`Py_SetProgramName` - * :c:func:`Py_SetPythonHome` * the configuration functions covered in :ref:`init-config` * Informative functions: @@ -780,33 +778,6 @@ deleted. This can be done using interpreter views. Process-wide parameters ----------------------- -.. c:function:: void Py_SetProgramName(const wchar_t *name) - - .. index:: - single: Py_Initialize() - single: main() - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.program_name` should be used instead, see :ref:`Python - Initialization Configuration `. - - This function should be called before :c:func:`Py_Initialize` is called for - the first time, if it is called at all. It tells the interpreter the value - of the ``argv[0]`` argument to the :c:func:`main` function of the program - (converted to wide characters). - This is used by some other functions below to find - the Python run-time libraries relative to the interpreter executable. The - default value is ``'python'``. The argument should point to a - zero-terminated wide character string in static storage whose contents will not - change for the duration of the program's execution. No code in the Python - interpreter will change the contents of this storage. - - Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:expr:`wchar_t*` string. - - .. deprecated-removed:: 3.11 3.16 - - .. c:function:: const char* Py_GetVersion() Return the version of this Python interpreter. This is a string that looks @@ -875,100 +846,3 @@ Process-wide parameters The returned string points into static storage; the caller should not modify its value. The value is available to Python code as part of the variable ``sys.version``. - - -.. c:function:: void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) - - .. index:: - single: main() - single: Py_FatalError() - single: argv (in module sys) - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.argv`, :c:member:`PyConfig.parse_argv` and - :c:member:`PyConfig.safe_path` should be used instead, see :ref:`Python - Initialization Configuration `. - - Set :data:`sys.argv` based on *argc* and *argv*. These parameters are - similar to those passed to the program's :c:func:`main` function with the - difference that the first entry should refer to the script file to be - executed rather than the executable hosting the Python interpreter. If there - isn't a script that will be run, the first entry in *argv* can be an empty - string. If this function fails to initialize :data:`sys.argv`, a fatal - condition is signalled using :c:func:`Py_FatalError`. - - If *updatepath* is zero, this is all the function does. If *updatepath* - is non-zero, the function also modifies :data:`sys.path` according to the - following algorithm: - - - If the name of an existing script is passed in ``argv[0]``, the absolute - path of the directory where the script is located is prepended to - :data:`sys.path`. - - Otherwise (that is, if *argc* is ``0`` or ``argv[0]`` doesn't point - to an existing file name), an empty string is prepended to - :data:`sys.path`, which is the same as prepending the current working - directory (``"."``). - - Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:expr:`wchar_t*` string. - - See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv` - members of the :ref:`Python Initialization Configuration `. - - .. note:: - It is recommended that applications embedding the Python interpreter - for purposes other than executing a single script pass ``0`` as *updatepath*, - and update :data:`sys.path` themselves if desired. - See :cve:`2008-5983`. - - On versions before 3.1.3, you can achieve the same effect by manually - popping the first :data:`sys.path` element after having called - :c:func:`PySys_SetArgv`, for example using:: - - PyRun_SimpleString("import sys; sys.path.pop(0)\n"); - - .. versionadded:: 3.1.3 - - .. deprecated-removed:: 3.11 3.16 - - -.. c:function:: void PySys_SetArgv(int argc, wchar_t **argv) - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.argv` and :c:member:`PyConfig.parse_argv` should be used - instead, see :ref:`Python Initialization Configuration `. - - This function works like :c:func:`PySys_SetArgvEx` with *updatepath* set - to ``1`` unless the :program:`python` interpreter was started with the - :option:`-I`. - - Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:expr:`wchar_t*` string. - - See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv` - members of the :ref:`Python Initialization Configuration `. - - .. versionchanged:: 3.4 The *updatepath* value depends on :option:`-I`. - - .. deprecated-removed:: 3.11 3.16 - - -.. c:function:: void Py_SetPythonHome(const wchar_t *home) - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.home` should be used instead, see :ref:`Python - Initialization Configuration `. - - Set the default "home" directory, that is, the location of the standard - Python libraries. See :envvar:`PYTHONHOME` for the meaning of the - argument string. - - The argument should point to a zero-terminated character string in static - storage whose contents will not change for the duration of the program's - execution. No code in the Python interpreter will change the contents of - this storage. - - Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:expr:`wchar_t*` string. - - .. deprecated-removed:: 3.11 3.16 diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 60c02aabeb89c5..c19a8a3083a430 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -2265,15 +2265,6 @@ PySys_GetObject:const char*:name:: PySys_GetXOptions:PyObject*::0: -PySys_SetArgv:void::: -PySys_SetArgv:int:argc:: -PySys_SetArgv:wchar_t**:argv:: - -PySys_SetArgvEx:void::: -PySys_SetArgvEx:int:argc:: -PySys_SetArgvEx:wchar_t**:argv:: -PySys_SetArgvEx:int:updatepath:: - PySys_SetObject:int::: PySys_SetObject:const char*:name:: PySys_SetObject:PyObject*:v:+1: @@ -3085,9 +3076,6 @@ Py_ReprEnter:PyObject*:object:+1: Py_ReprLeave:void::: Py_ReprLeave:PyObject*:object:-1: -Py_SetProgramName:void::: -Py_SetProgramName:const wchar_t*:name:: - Py_XDECREF:void::: Py_XDECREF:PyObject*:o:-1:if o is not NULL diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 8362b1ef7e312b..b301e56f306c37 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -1131,6 +1131,11 @@ Deprecated C APIs Removed C APIs -------------- +* Remove :c:func:`Py_SetProgramName`, :c:func:`Py_SetPythonHome`, + :c:func:`PySys_SetArgv` and :c:func:`!PySys_SetArgvEx` functions, + deprecated since Python 3.11. + (Contributed by Victor Stinner in :gh:`158001`.) + * The :c:var:`!PyUnstable_ExecutableKinds` array, as well as the macros :c:macro:`!PyUnstable_EXECUTABLE_KIND_SKIP`, :c:macro:`!PyUnstable_EXECUTABLE_KIND_PY_FUNCTION`, diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 4b3474035cec19..f11ac4d2a9f10e 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -33,10 +33,6 @@ PyAPI_FUNC(void) _Py_NO_RETURN Py_Exit(int); PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv); PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv); -/* In pathconfig.c */ -Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *); -Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetPythonHome(const wchar_t *); - #ifdef MS_WINDOWS int _Py_CheckPython3(void); #endif diff --git a/Include/sysmodule.h b/Include/sysmodule.h index b7d800c5e5db0b..fc6da6f4c797b3 100644 --- a/Include/sysmodule.h +++ b/Include/sysmodule.h @@ -13,9 +13,6 @@ PyAPI_FUNC(int) PySys_GetOptionalAttrString(const char *, PyObject **); PyAPI_FUNC(PyObject *) PySys_GetObject(const char *); PyAPI_FUNC(int) PySys_SetObject(const char *, PyObject *); -Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetArgv(int, wchar_t **); -Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetArgvEx(int, wchar_t **, int); - PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...) Py_GCC_ATTRIBUTE((format(printf, 1, 2))); PyAPI_FUNC(void) PySys_WriteStderr(const char *format, ...) diff --git a/Misc/NEWS.d/next/C_API/2026-09-23-21-45-43.gh-issue-158001.R_wX4E.rst b/Misc/NEWS.d/next/C_API/2026-09-23-21-45-43.gh-issue-158001.R_wX4E.rst new file mode 100644 index 00000000000000..1f9bf8a9beabf8 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-09-23-21-45-43.gh-issue-158001.R_wX4E.rst @@ -0,0 +1,3 @@ +Remove :c:func:`Py_SetProgramName`, :c:func:`Py_SetPythonHome`, +:c:func:`PySys_SetArgv` and :c:func:`!PySys_SetArgvEx` functions, deprecated +since Python 3.11. Patch by Victor Stinner. diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 17b93ba47caac4..7e82a6365d9808 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -23,6 +23,10 @@ extern void PySys_AddWarnOption(const wchar_t *s); extern void PySys_AddXOption(const wchar_t *s); extern void Py_SetPath(const wchar_t *path); +// Functions removed from Python 3.16 API but still exported for the stable +// ABI. +extern void Py_SetPythonHome(const wchar_t *); + // These functions were removed from Python 3.15 API but are still exported // for the stable ABI. We want to test them in this program. extern void PySys_ResetWarnOptions(void); diff --git a/Python/pathconfig.c b/Python/pathconfig.c index d034562c43f23c..b4ba1c52066879 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -236,7 +236,8 @@ Py_SetPath(const wchar_t *path) } -void +// Function removed from Python 3.16 limited C API, but kept in the stable ABI +PyAPI_FUNC(void) Py_SetPythonHome(const wchar_t *home) { int has_value = home && home[0]; @@ -254,7 +255,8 @@ Py_SetPythonHome(const wchar_t *home) } -void +// Function removed from Python 3.16 limited C API, but kept in the stable ABI +PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *program_name) { int has_value = program_name && program_name[0]; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index b3ec8461485de1..718ae51944faf2 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -4490,7 +4490,8 @@ make_sys_argv(int argc, wchar_t * const * argv) return list; } -void +// Function removed from Python 3.16 limited C API, but kept in the stable ABI +PyAPI_FUNC(void) PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) { wchar_t* empty_argv[1] = {L""}; @@ -4537,7 +4538,8 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) } } -void +// Function removed from Python 3.16 limited C API, but kept in the stable ABI +PyAPI_FUNC(void) PySys_SetArgv(int argc, wchar_t **argv) { int isolated = 0; @@ -4547,10 +4549,7 @@ PySys_SetArgv(int argc, wchar_t **argv) isolated = config->isolated; } -_Py_COMP_DIAG_PUSH -_Py_COMP_DIAG_IGNORE_DEPR_DECLS PySys_SetArgvEx(argc, argv, isolated == 0); -_Py_COMP_DIAG_POP } /* Reimplementation of PyFile_WriteString() no calling indirectly From b13837eeba7744f7934569640a53286cca9a4029 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Sep 2026 21:55:40 +0200 Subject: [PATCH 2/5] doc: Don't link to removed functions --- Doc/whatsnew/3.16.rst | 4 ++-- .../next/C_API/2026-09-23-21-45-43.gh-issue-158001.R_wX4E.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index b301e56f306c37..017de5ebabd6a9 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -1131,8 +1131,8 @@ Deprecated C APIs Removed C APIs -------------- -* Remove :c:func:`Py_SetProgramName`, :c:func:`Py_SetPythonHome`, - :c:func:`PySys_SetArgv` and :c:func:`!PySys_SetArgvEx` functions, +* Remove :c:func:`!Py_SetProgramName`, :c:func:`!Py_SetPythonHome`, + :c:func:`!PySys_SetArgv` and :c:func:`!PySys_SetArgvEx` functions, deprecated since Python 3.11. (Contributed by Victor Stinner in :gh:`158001`.) diff --git a/Misc/NEWS.d/next/C_API/2026-09-23-21-45-43.gh-issue-158001.R_wX4E.rst b/Misc/NEWS.d/next/C_API/2026-09-23-21-45-43.gh-issue-158001.R_wX4E.rst index 1f9bf8a9beabf8..2da45967b24597 100644 --- a/Misc/NEWS.d/next/C_API/2026-09-23-21-45-43.gh-issue-158001.R_wX4E.rst +++ b/Misc/NEWS.d/next/C_API/2026-09-23-21-45-43.gh-issue-158001.R_wX4E.rst @@ -1,3 +1,3 @@ -Remove :c:func:`Py_SetProgramName`, :c:func:`Py_SetPythonHome`, -:c:func:`PySys_SetArgv` and :c:func:`!PySys_SetArgvEx` functions, deprecated +Remove :c:func:`!Py_SetProgramName`, :c:func:`!Py_SetPythonHome`, +:c:func:`!PySys_SetArgv` and :c:func:`!PySys_SetArgvEx` functions, deprecated since Python 3.11. Patch by Victor Stinner. From da466c9ad2da3513bc6a97ea76240c983b55739b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Sep 2026 22:31:55 +0200 Subject: [PATCH 3/5] Fix make check-limited-abi Mark the 4 functions as abi_only in stable_abi.toml. --- Doc/data/stable_abi.dat | 4 ---- Misc/stable_abi.toml | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 3fbff9a0d65362..dc7d3330927d5a 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -718,8 +718,6 @@ func,PySys_GetObject,3.2,, func,PySys_GetOptionalAttr,3.15,, func,PySys_GetOptionalAttrString,3.15,, func,PySys_GetXOptions,3.7,, -func,PySys_SetArgv,3.2,, -func,PySys_SetArgvEx,3.2,, func,PySys_SetObject,3.2,, func,PySys_WriteStderr,3.2,, func,PySys_WriteStdout,3.2,, @@ -994,8 +992,6 @@ func,Py_ReprEnter,3.2,, func,Py_ReprLeave,3.2,, func,Py_SET_SIZE,3.15,, func,Py_SIZE,3.15,, -func,Py_SetProgramName,3.2,, -func,Py_SetPythonHome,3.2,, func,Py_SetRecursionLimit,3.2,, macro,Py_TPFLAGS_BASETYPE,3.2,, macro,Py_TPFLAGS_DEFAULT,3.2,, diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 8ae17142dcc67a..f4b28543ff1344 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -1349,8 +1349,10 @@ abi_only = true [function.PySys_SetArgv] added = '3.2' + abi_only = true [function.PySys_SetArgvEx] added = '3.2' + abi_only = true [function.PySys_SetObject] added = '3.2' [function.PySys_SetPath] @@ -1694,8 +1696,10 @@ added = '3.2' [function.Py_SetProgramName] added = '3.2' + abi_only = true [function.Py_SetPythonHome] added = '3.2' + abi_only = true [function.Py_SetRecursionLimit] added = '3.2' [function.Py_VaBuildValue] From 882795fa0dcdd54f57cbfdae9bb3ffe3dee6c9fb Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Sep 2026 22:34:44 +0200 Subject: [PATCH 4/5] Update Doc/tools/removed-ids.txt --- Doc/tools/removed-ids.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Doc/tools/removed-ids.txt b/Doc/tools/removed-ids.txt index be3c2f38f194ec..b01c3b49951295 100644 --- a/Doc/tools/removed-ids.txt +++ b/Doc/tools/removed-ids.txt @@ -3,6 +3,10 @@ # Remove from here in 3.16 c-api/allocation.html: deprecated-aliases c-api/file.html: deprecated-api +c-api/interp-lifecycle.html: c.PySys_SetArgv +c-api/interp-lifecycle.html: c.PySys_SetArgvEx +c-api/interp-lifecycle.html: c.Py_SetProgramName +c-api/interp-lifecycle.html: c.Py_SetPythonHome # Removed sections library/asyncio-task.html: terminating-a-task-group From 251156bc21fd9b5573e5094287e691304114a729 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 24 Sep 2026 10:54:45 +0200 Subject: [PATCH 5/5] Explain how to update existing code --- Doc/whatsnew/3.16.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 017de5ebabd6a9..974059ff67dfdd 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -1131,9 +1131,15 @@ Deprecated C APIs Removed C APIs -------------- -* Remove :c:func:`!Py_SetProgramName`, :c:func:`!Py_SetPythonHome`, - :c:func:`!PySys_SetArgv` and :c:func:`!PySys_SetArgvEx` functions, - deprecated since Python 3.11. +* Remove :c:func:`!Py_SetProgramName` and :c:func:`!Py_SetPythonHome` + functions, deprecated since Python 3.11. Instead, use :ref:`PyInitConfig C + API ` to set respectively ``"program_name"`` and + ``"home"``. + (Contributed by Victor Stinner in :gh:`158001`.) + +* Remove :c:func:`!PySys_SetArgv` and :c:func:`!PySys_SetArgvEx` functions, + deprecated since Python 3.11. Instead, set directly :data:`sys.argv`, and + maybe also :data:`sys.path`. (Contributed by Victor Stinner in :gh:`158001`.) * The :c:var:`!PyUnstable_ExecutableKinds` array, as well as the macros