https://github.com/python/cpython/commit/a5a4659548ed112692c7617a295577f0e6eee6df
commit: a5a4659548ed112692c7617a295577f0e6eee6df
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-09-24T12:52:54+02:00
summary:

gh-158001: Remove Py_SetProgramName() function (#158024)

Remove Py_SetProgramName(), Py_SetPythonHome(), PySys_SetArgv() and
PySys_SetArgvEx() functions, deprecated since Python 3.11.

Mark the 4 functions as abi_only in stable_abi.toml.

files:
A Misc/NEWS.d/next/C_API/2026-09-23-21-45-43.gh-issue-158001.R_wX4E.rst
M Doc/c-api/interp-lifecycle.rst
M Doc/data/refcounts.dat
M Doc/data/stable_abi.dat
M Doc/tools/removed-ids.txt
M Doc/whatsnew/3.16.rst
M Include/pylifecycle.h
M Include/sysmodule.h
M Misc/stable_abi.toml
M Programs/_testembed.c
M Python/pathconfig.c
M Python/sysmodule.c

diff --git a/Doc/c-api/interp-lifecycle.rst b/Doc/c-api/interp-lifecycle.rst
index a38d8cec827746..6f832b7a34b10b 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:
@@ -778,33 +776,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 <init-config>`.
-
-   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
@@ -873,100 +844,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 <init-config>`.
-
-   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 <init-config>`.
-
-   .. 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 <init-config>`.
-
-   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 <init-config>`.
-
-   .. 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 <init-config>`.
-
-   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/data/stable_abi.dat b/Doc/data/stable_abi.dat
index 65f0e5f52bd936..662158323c5d30 100644
--- a/Doc/data/stable_abi.dat
+++ b/Doc/data/stable_abi.dat
@@ -717,8 +717,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,,
@@ -993,8 +991,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/Doc/tools/removed-ids.txt b/Doc/tools/removed-ids.txt
index a6fb127a1e92ae..3f7906ee84ec14 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
 c-api/threads.html: c.PyEval_InitThreads
 
 # Removed sections
diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst
index 8010379323e721..c76681261f6746 100644
--- a/Doc/whatsnew/3.16.rst
+++ b/Doc/whatsnew/3.16.rst
@@ -1145,6 +1145,17 @@ Removed C APIs
   3.7 and was deprecated since Python 3.9.
   (Contributed by Victor Stinner in :gh:`154757`.)
 
+* Remove :c:func:`!Py_SetProgramName` and :c:func:`!Py_SetPythonHome`
+  functions, deprecated since Python 3.11. Instead, use :ref:`PyInitConfig C
+  API <pyinitconfig_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
   :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..2da45967b24597
--- /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/Misc/stable_abi.toml b/Misc/stable_abi.toml
index b7a1e49c8bf480..08fd7009dbc4b8 100644
--- a/Misc/stable_abi.toml
+++ b/Misc/stable_abi.toml
@@ -1350,8 +1350,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]
@@ -1695,8 +1697,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]
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

_______________________________________________
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