gh-105145: Remove old functions to config Python init (#105154)

Remove the following old functions to configure the Python
initialization, deprecated in Python 3.11:

* PySys_AddWarnOptionUnicode()
* PySys_AddWarnOption()
* PySys_AddXOption()
* PySys_HasWarnOptions()
* PySys_SetArgvEx()
* PySys_SetArgv()
* PySys_SetPath()
* Py_SetPath()
* Py_SetProgramName()
* Py_SetPythonHome()
* Py_SetStandardStreamEncoding()
* _Py_SetProgramFullPath()

Most of these functions are kept in the stable ABI, except:

* Py_SetStandardStreamEncoding()
* _Py_SetProgramFullPath()

Update Doc/extending/embedding.rst and Doc/extending/extending.rst to
use the new PyConfig API.

_testembed.c:

* check_stdio_details() now sets stdio_encoding and stdio_errors
  of PyConfig.
* Add definitions of functions removed from the API but kept in the
  stable ABI.
* test_init_from_config() and test_init_read_set() now use
  PyConfig_SetString() instead of PyConfig_SetBytesString().

Remove _Py_ClearStandardStreamEncoding() internal function.
This commit is contained in:
Victor Stinner 2023-06-01 09:14:02 +02:00 committed by GitHub
parent 8ed705c083
commit 424049cc11
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 182 additions and 522 deletions

View file

@ -29,12 +29,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_SetPath`
* :c:func:`Py_SetProgramName`
* :c:func:`Py_SetPythonHome`
* :c:func:`Py_SetStandardStreamEncoding`
* :c:func:`PySys_AddWarnOption`
* :c:func:`PySys_AddXOption`
* :c:func:`PySys_ResetWarnOptions`
* Informative functions:
@ -332,7 +326,6 @@ Initializing and finalizing the interpreter
.. c:function:: void Py_Initialize()
.. index::
single: Py_SetProgramName()
single: PyEval_InitThreads()
single: modules (in module sys)
single: path (in module sys)
@ -340,8 +333,6 @@ Initializing and finalizing the interpreter
pair: module; __main__
pair: module; sys
triple: module; search; path
single: PySys_SetArgv()
single: PySys_SetArgvEx()
single: Py_FinalizeEx()
Initialize the Python interpreter. In an application embedding Python,
@ -352,7 +343,9 @@ Initializing and finalizing the interpreter
the table of loaded modules (``sys.modules``), and creates the fundamental
modules :mod:`builtins`, :mod:`__main__` and :mod:`sys`. It also initializes
the module search path (``sys.path``). It does not set ``sys.argv``; use
:c:func:`PySys_SetArgvEx` for that. This is a no-op when called for a second time
the new :c:type:`PyConfig` API of the :ref:`Python Initialization
Configuration <init-config>` for that. This is a no-op when called for a
second time
(without calling :c:func:`Py_FinalizeEx` first). There is no return value; it is a
fatal error if the initialization fails.
@ -425,76 +418,9 @@ Process-wide parameters
=======================
.. c:function:: int Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
.. index::
single: Py_Initialize()
single: main()
triple: stdin; stdout; sdterr
This API is kept for backward compatibility: setting
:c:member:`PyConfig.stdio_encoding` and :c:member:`PyConfig.stdio_errors`
should be used instead, see :ref:`Python Initialization Configuration
<init-config>`.
This function should be called before :c:func:`Py_Initialize`, if it is
called at all. It specifies which encoding and error handling to use
with standard IO, with the same meanings as in :func:`str.encode`.
It overrides :envvar:`PYTHONIOENCODING` values, and allows embedding code
to control IO encoding when the environment variable does not work.
*encoding* and/or *errors* may be ``NULL`` to use
:envvar:`PYTHONIOENCODING` and/or default values (depending on other
settings).
Note that :data:`sys.stderr` always uses the "backslashreplace" error
handler, regardless of this (or any other) setting.
If :c:func:`Py_FinalizeEx` is called, this function will need to be called
again in order to affect subsequent calls to :c:func:`Py_Initialize`.
Returns ``0`` if successful, a nonzero value on error (e.g. calling after the
interpreter has already been initialized).
.. versionadded:: 3.4
.. deprecated:: 3.11
.. c:function:: void Py_SetProgramName(const wchar_t *name)
.. index::
single: Py_Initialize()
single: main()
single: Py_GetPath()
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 :c:func:`Py_GetPath` and 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_*` string.
.. deprecated:: 3.11
.. c:function:: wchar* Py_GetProgramName()
.. index:: single: Py_SetProgramName()
Return the program name set with :c:func:`Py_SetProgramName`, or the default.
Return the program name set with :c:member:`PyConfig.program_name`, or the default.
The returned string points into static storage; the caller should not modify its
value.
@ -509,7 +435,7 @@ Process-wide parameters
Return the *prefix* for installed platform-independent files. This is derived
through a number of complicated rules from the program name set with
:c:func:`Py_SetProgramName` and some environment variables; for example, if the
:c:member:`PyConfig.program_name` and some environment variables; for example, if the
program name is ``'/usr/local/bin/python'``, the prefix is ``'/usr/local'``. The
returned string points into static storage; the caller should not modify its
value. This corresponds to the :makevar:`prefix` variable in the top-level
@ -528,7 +454,7 @@ Process-wide parameters
Return the *exec-prefix* for installed platform-*dependent* files. This is
derived through a number of complicated rules from the program name set with
:c:func:`Py_SetProgramName` and some environment variables; for example, if the
:c:member:`PyConfig.program_name` and some environment variables; for example, if the
program name is ``'/usr/local/bin/python'``, the exec-prefix is
``'/usr/local'``. The returned string points into static storage; the caller
should not modify its value. This corresponds to the :makevar:`exec_prefix`
@ -568,12 +494,11 @@ Process-wide parameters
.. c:function:: wchar_t* Py_GetProgramFullPath()
.. index::
single: Py_SetProgramName()
single: executable (in module sys)
Return the full program name of the Python executable; this is computed as a
side-effect of deriving the default module search path from the program name
(set by :c:func:`Py_SetProgramName` above). The returned string points into
(set by :c:member:`PyConfig.program_name`). The returned string points into
static storage; the caller should not modify its value. The value is available
to Python code as ``sys.executable``.
@ -589,10 +514,9 @@ Process-wide parameters
.. index::
triple: module; search; path
single: path (in module sys)
single: Py_SetPath()
Return the default module search path; this is computed from the program name
(set by :c:func:`Py_SetProgramName` above) and some environment variables.
(set by :c:member:`PyConfig.program_name`) and some environment variables.
The returned string consists of a series of directory names separated by a
platform dependent delimiter character. The delimiter character is ``':'``
on Unix and macOS, ``';'`` on Windows. The returned string points into
@ -610,44 +534,6 @@ Process-wide parameters
It now returns ``NULL`` if called before :c:func:`Py_Initialize`.
.. c:function:: void Py_SetPath(const wchar_t *)
.. index::
triple: module; search; path
single: path (in module sys)
single: Py_GetPath()
This API is kept for backward compatibility: setting
:c:member:`PyConfig.module_search_paths` and
:c:member:`PyConfig.module_search_paths_set` should be used instead, see
:ref:`Python Initialization Configuration <init-config>`.
Set the default module search path. If this function is called before
:c:func:`Py_Initialize`, then :c:func:`Py_GetPath` won't attempt to compute a
default search path but uses the one provided instead. This is useful if
Python is embedded by an application that has full knowledge of the location
of all modules. The path components should be separated by the platform
dependent delimiter character, which is ``':'`` on Unix and macOS, ``';'``
on Windows.
This also causes :data:`sys.executable` to be set to the program
full path (see :c:func:`Py_GetProgramFullPath`) and for :data:`sys.prefix` and
:data:`sys.exec_prefix` to be empty. It is up to the caller to modify these
if required after calling :c:func:`Py_Initialize`.
Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a
:c:expr:`wchar_*` string.
The path argument is copied internally, so the caller may free it after the
call completes.
.. versionchanged:: 3.8
The program full path is now used for :data:`sys.executable`, instead
of the program name.
.. deprecated:: 3.11
.. c:function:: const char* Py_GetVersion()
Return the version of this Python interpreter. This is a string that looks
@ -718,110 +604,10 @@ Process-wide parameters
``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_*` 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 <https://cve.mitre.org/cgi-bin/cvename.cgi?name=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
.. XXX impl. doesn't seem consistent in allowing ``0``/``NULL`` for the params;
check w/ Guido.
.. deprecated:: 3.11
.. 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_*` 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:: 3.11
.. 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_*` string.
.. deprecated:: 3.11
.. c:function:: wchar_t* Py_GetPythonHome()
Return the default "home", that is, the value set by a previous call to
:c:func:`Py_SetPythonHome`, or the value of the :envvar:`PYTHONHOME`
Return the default "home", that is, the value set by
:c:member:`PyConfig.home`, or the value of the :envvar:`PYTHONHOME`
environment variable if it is set.
This function should not be called before :c:func:`Py_Initialize`, otherwise

View file

@ -531,7 +531,17 @@ PyConfig
.. c:member:: PyWideStringList argv
Command line arguments: :data:`sys.argv`.
.. index::
single: main()
single: argv (in module sys)
Set :data:`sys.argv` command line arguments based on
:c:member:`~PyConfig.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 :c:member:`~PyConfig.argv` can be an
empty string.
Set :c:member:`~PyConfig.parse_argv` to ``1`` to parse
:c:member:`~PyConfig.argv` the same way the regular Python parses Python
@ -572,6 +582,8 @@ PyConfig
Part of the :ref:`Python Path Configuration <init-path-config>` output.
See also :c:member:`PyConfig.exec_prefix`.
.. c:member:: wchar_t* base_executable
Python base executable: :data:`sys._base_executable`.
@ -584,6 +596,8 @@ PyConfig
Part of the :ref:`Python Path Configuration <init-path-config>` output.
See also :c:member:`PyConfig.executable`.
.. c:member:: wchar_t* base_prefix
:data:`sys.base_prefix`.
@ -592,6 +606,8 @@ PyConfig
Part of the :ref:`Python Path Configuration <init-path-config>` output.
See also :c:member:`PyConfig.prefix`.
.. c:member:: int buffered_stdio
If equals to ``0`` and :c:member:`~PyConfig.configure_c_stdio` is non-zero,
@ -700,6 +716,8 @@ PyConfig
Part of the :ref:`Python Path Configuration <init-path-config>` output.
See also :c:member:`PyConfig.base_exec_prefix`.
.. c:member:: wchar_t* executable
The absolute path of the executable binary for the Python interpreter:
@ -709,6 +727,8 @@ PyConfig
Part of the :ref:`Python Path Configuration <init-path-config>` output.
See also :c:member:`PyConfig.base_executable`.
.. c:member:: int faulthandler
Enable faulthandler?
@ -780,10 +800,8 @@ PyConfig
.. c:member:: wchar_t* home
Python home directory.
If :c:func:`Py_SetPythonHome` has been called, use its argument if it is
not ``NULL``.
Set the default Python "home" directory, that is, the location of the
standard Python libraries (see :envvar:`PYTHONHOME`).
Set by the :envvar:`PYTHONHOME` environment variable.
@ -1029,12 +1047,13 @@ PyConfig
Part of the :ref:`Python Path Configuration <init-path-config>` output.
See also :c:member:`PyConfig.base_prefix`.
.. c:member:: wchar_t* program_name
Program name used to initialize :c:member:`~PyConfig.executable` and in
early error messages during Python initialization.
* If :func:`Py_SetProgramName` has been called, use its argument.
* On macOS, use :envvar:`PYTHONEXECUTABLE` environment variable if set.
* If the ``WITH_NEXT_FRAMEWORK`` macro is defined, use
:envvar:`__PYVENV_LAUNCHER__` environment variable if set.
@ -1144,9 +1163,6 @@ PyConfig
:data:`sys.stderr` (but :data:`sys.stderr` always uses
``"backslashreplace"`` error handler).
If :c:func:`Py_SetStandardStreamEncoding` has been called, use its
*error* and *errors* arguments if they are not ``NULL``.
Use the :envvar:`PYTHONIOENCODING` environment variable if it is
non-empty.
@ -1162,6 +1178,8 @@ PyConfig
or if the LC_CTYPE locale is "C" or "POSIX".
* ``"strict"`` otherwise.
See also :c:member:`PyConfig.legacy_windows_stdio`.
.. c:member:: int tracemalloc
Enable tracemalloc?
@ -1509,7 +1527,7 @@ If a ``._pth`` file is present:
* Set :c:member:`~PyConfig.safe_path` to ``1``.
The ``__PYVENV_LAUNCHER__`` environment variable is used to set
:c:member:`PyConfig.base_executable`
:c:member:`PyConfig.base_executable`.
Py_RunMain()

View file

@ -739,14 +739,14 @@ environment variable :envvar:`PYTHONHOME`, or insert additional directories in
front of the standard path by setting :envvar:`PYTHONPATH`.
.. index::
single: Py_SetProgramName()
single: Py_GetPath()
single: Py_GetPrefix()
single: Py_GetExecPrefix()
single: Py_GetProgramFullPath()
The embedding application can steer the search by calling
``Py_SetProgramName(file)`` *before* calling :c:func:`Py_Initialize`. Note that
The embedding application can steer the search by setting
:c:member:`PyConfig.program_name` *before* calling
:c:func:`Py_InitializeFromConfig`. Note that
:envvar:`PYTHONHOME` still overrides this and :envvar:`PYTHONPATH` is still
inserted in front of the standard path. An application that requires total
control has to provide its own implementation of :c:func:`Py_GetPath`,

View file

@ -237,46 +237,6 @@ accessible to C code. They all work with the current interpreter thread's
Reset :data:`sys.warnoptions` to an empty list. This function may be
called prior to :c:func:`Py_Initialize`.
.. c:function:: void PySys_AddWarnOption(const wchar_t *s)
This API is kept for backward compatibility: setting
:c:member:`PyConfig.warnoptions` should be used instead, see :ref:`Python
Initialization Configuration <init-config>`.
Append *s* to :data:`sys.warnoptions`. This function must be called prior
to :c:func:`Py_Initialize` in order to affect the warnings filter list.
.. deprecated:: 3.11
.. c:function:: void PySys_AddWarnOptionUnicode(PyObject *unicode)
This API is kept for backward compatibility: setting
:c:member:`PyConfig.warnoptions` should be used instead, see :ref:`Python
Initialization Configuration <init-config>`.
Append *unicode* to :data:`sys.warnoptions`.
Note: this function is not currently usable from outside the CPython
implementation, as it must be called prior to the implicit import of
:mod:`warnings` in :c:func:`Py_Initialize` to be effective, but can't be
called until enough of the runtime has been initialized to permit the
creation of Unicode objects.
.. deprecated:: 3.11
.. c:function:: void PySys_SetPath(const wchar_t *path)
This API is kept for backward compatibility: setting
:c:member:`PyConfig.module_search_paths` and
:c:member:`PyConfig.module_search_paths_set` should be used instead, see
:ref:`Python Initialization Configuration <init-config>`.
Set :data:`sys.path` to a list object of paths found in *path* which should
be a list of paths separated with the platform's search path delimiter
(``:`` on Unix, ``;`` on Windows).
.. deprecated:: 3.11
.. c:function:: void PySys_WriteStdout(const char *format, ...)
Write the output string described by *format* to :data:`sys.stdout`. No
@ -313,20 +273,6 @@ accessible to C code. They all work with the current interpreter thread's
.. versionadded:: 3.2
.. c:function:: void PySys_AddXOption(const wchar_t *s)
This API is kept for backward compatibility: setting
:c:member:`PyConfig.xoptions` should be used instead, see :ref:`Python
Initialization Configuration <init-config>`.
Parse *s* as a set of :option:`-X` options and add them to the current
options mapping as returned by :c:func:`PySys_GetXOptions`. This function
may be called prior to :c:func:`Py_Initialize`.
.. versionadded:: 3.2
.. deprecated:: 3.11
.. c:function:: PyObject *PySys_GetXOptions()
Return the current dictionary of :option:`-X` options, similarly to

View file

@ -596,19 +596,12 @@ function,PyStructSequence_NewType,3.2,,
function,PyStructSequence_SetItem,3.2,,
var,PyStructSequence_UnnamedField,3.11,,
var,PySuper_Type,3.2,,
function,PySys_AddWarnOption,3.2,,
function,PySys_AddWarnOptionUnicode,3.2,,
function,PySys_AddXOption,3.7,,
function,PySys_FormatStderr,3.2,,
function,PySys_FormatStdout,3.2,,
function,PySys_GetObject,3.2,,
function,PySys_GetXOptions,3.7,,
function,PySys_HasWarnOptions,3.2,,
function,PySys_ResetWarnOptions,3.2,,
function,PySys_SetArgv,3.2,,
function,PySys_SetArgvEx,3.2,,
function,PySys_SetObject,3.2,,
function,PySys_SetPath,3.2,,
function,PySys_WriteStderr,3.2,,
function,PySys_WriteStdout,3.2,,
type,PyThreadState,3.2,,opaque
@ -850,9 +843,6 @@ function,Py_NewInterpreter,3.2,,
function,Py_NewRef,3.10,,
function,Py_ReprEnter,3.2,,
function,Py_ReprLeave,3.2,,
function,Py_SetPath,3.7,,
function,Py_SetProgramName,3.2,,
function,Py_SetPythonHome,3.2,,
function,Py_SetRecursionLimit,3.2,,
type,Py_UCS4,3.2,,
macro,Py_UNBLOCK_THREADS,3.2,,

View file

@ -59,24 +59,36 @@ perform some operation on a file. ::
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
PyStatus status;
PyConfig config;
PyConfig_InitPythonConfig(&config);
/* optional but recommended */
status = PyConfig_SetBytesString(&config, &config.program_name, argv[0]);
if (PyStatus_Exception(status)) {
goto exception;
}
Py_SetProgramName(program); /* optional but recommended */
Py_Initialize();
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
goto exception;
}
PyConfig_Clear(&config);
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
exception:
PyConfig_Clear(&config);
Py_ExitStatusException(status);
}
The :c:func:`Py_SetProgramName` function should be called before
:c:func:`Py_Initialize` to inform the interpreter about paths to Python run-time
Setting :c:member:`PyConfig.program_name` should be called before
:c:func:`Py_InitializeFromConfig` to inform the interpreter about paths to Python run-time
libraries. Next, the Python interpreter is initialized with
:c:func:`Py_Initialize`, followed by the execution of a hard-coded Python script
that prints the date and time. Afterwards, the :c:func:`Py_FinalizeEx` call shuts

View file

@ -383,14 +383,15 @@ automatically unless there's an entry in the :c:data:`PyImport_Inittab` table.
To add the module to the initialization table, use :c:func:`PyImport_AppendInittab`,
optionally followed by an import of the module::
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
PyStatus status;
PyConfig config;
PyConfig_InitPythonConfig(&config);
/* Add a built-in module, before Py_Initialize */
if (PyImport_AppendInittab("spam", PyInit_spam) == -1) {
@ -399,11 +400,18 @@ optionally followed by an import of the module::
}
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(program);
status = PyConfig_SetBytesString(&config, &config.program_name, argv[0]);
if (PyStatus_Exception(status)) {
goto exception;
}
/* Initialize the Python interpreter. Required.
If this step fails, it will be a fatal error. */
Py_Initialize();
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
goto exception;
}
PyConfig_Clear(&config);
/* Optionally import the module; alternatively,
import can be deferred until the embedded script
@ -414,10 +422,13 @@ optionally followed by an import of the module::
fprintf(stderr, "Error: could not import module 'spam'\n");
}
...
// ... use Python C API here ...
PyMem_RawFree(program);
return 0;
exception:
PyConfig_Clear(&config);
Py_ExitStatusException(status);
}
.. note::

View file

@ -99,8 +99,7 @@ Embedded Python
If Python is embedded within another application :c:func:`Py_InitializeFromConfig` and
the :c:type:`PyConfig` structure can be used to initialize Python. The path specific
details are described at :ref:`init-path-config`. Alternatively the older :c:func:`Py_SetPath`
can be used to bypass the initialization of the module search path.
details are described at :ref:`init-path-config`.
.. seealso::

View file

@ -1169,8 +1169,8 @@ following advice will prevent conflicts with other installations:
listed.
* If you are loading :file:`python3.dll` or :file:`python37.dll` in your own
executable, explicitly call :c:func:`Py_SetPath` or (at least)
:c:func:`Py_SetProgramName` before :c:func:`Py_Initialize`.
executable, explicitly set :c:member:`PyConfig.module_search_paths` before
:c:func:`Py_InitializeFromConfig`.
* Clear and/or overwrite :envvar:`PYTHONPATH` and set :envvar:`PYTHONHOME`
before launching :file:`python.exe` from your application.

View file

@ -375,3 +375,23 @@ Removed
* ``PyEval_CallMethod()``: use :c:func:`PyObject_CallMethod` instead.
(Contributed by Victor Stinner in :gh:`105107`.)
* Remove the following old functions to configure the Python initialization,
deprecated in Python 3.11:
* ``PySys_AddWarnOptionUnicode()``: use :c:member:`PyConfig.warnoptions` instead.
* ``PySys_AddWarnOption()``: use :c:member:`PyConfig.warnoptions` instead.
* ``PySys_AddXOption()``: use :c:member:`PyConfig.xoptions` instead.
* ``PySys_HasWarnOptions()``: use :c:member:`PyConfig.xoptions` instead.
* ``PySys_SetArgvEx()``: set :c:member:`PyConfig.argv` instead.
* ``PySys_SetArgv()``: set :c:member:`PyConfig.argv` instead.
* ``PySys_SetPath()``: set :c:member:`PyConfig.module_search_paths` instead.
* ``Py_SetPath()``: set :c:member:`PyConfig.module_search_paths` instead.
* ``Py_SetProgramName()``: set :c:member:`PyConfig.program_name` instead.
* ``Py_SetPythonHome()``: set :c:member:`PyConfig.home` instead.
* ``Py_SetStandardStreamEncoding()``: set :c:member:`PyConfig.stdio_encoding` instead.
* ``_Py_SetProgramFullPath()``: set :c:member:`PyConfig.executable` instead.
Use the new :c:type:`PyConfig` API of the :ref:`Python Initialization
Configuration <init-config>` instead (:pep:`587`), added to Python 3.8.
(Contributed by Victor Stinner in :gh:`105145`.)

View file

@ -6,13 +6,6 @@
in all builds of Python */
PyAPI_FUNC(int) Py_FrozenMain(int argc, char **argv);
/* Only used by applications that embed the interpreter and need to
* override the standard encoding determination mechanism
*/
Py_DEPRECATED(3.11) PyAPI_FUNC(int) Py_SetStandardStreamEncoding(
const char *encoding,
const char *errors);
/* PEP 432 Multi-phase initialization API (Private while provisional!) */
PyAPI_FUNC(PyStatus) Py_PreInitialize(
@ -46,8 +39,6 @@ PyAPI_FUNC(void) _Py_RestoreSignals(void);
PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *);
PyAPI_FUNC(int) _Py_FdIsInteractive(FILE *fp, PyObject *filename);
Py_DEPRECATED(3.11) PyAPI_FUNC(void) _Py_SetProgramFullPath(const wchar_t *);
PyAPI_FUNC(const char *) _Py_gitidentifier(void);
PyAPI_FUNC(const char *) _Py_gitversion(void);

View file

@ -23,8 +23,6 @@ extern PyStatus _PyUnicode_InitEncodings(PyThreadState *tstate);
extern int _PyUnicode_EnableLegacyWindowsFSEncoding(void);
#endif
PyAPI_FUNC(void) _Py_ClearStandardStreamEncoding(void);
PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc);
/* Various one-time initializers */

View file

@ -34,18 +34,12 @@ 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 *);
PyAPI_FUNC(wchar_t *) Py_GetProgramName(void);
Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetPythonHome(const wchar_t *);
PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void);
PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void);
PyAPI_FUNC(wchar_t *) Py_GetPrefix(void);
PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
PyAPI_FUNC(wchar_t *) Py_GetPath(void);
Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetPath(const wchar_t *);
#ifdef MS_WINDOWS
int _Py_CheckPython3(void);
#endif

View file

@ -10,10 +10,6 @@ extern "C" {
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);
Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetPath(const wchar_t *);
PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...)
Py_GCC_ATTRIBUTE((format(printf, 1, 2)));
PyAPI_FUNC(void) PySys_WriteStderr(const char *format, ...)
@ -22,11 +18,7 @@ PyAPI_FUNC(void) PySys_FormatStdout(const char *format, ...);
PyAPI_FUNC(void) PySys_FormatStderr(const char *format, ...);
PyAPI_FUNC(void) PySys_ResetWarnOptions(void);
Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_AddWarnOption(const wchar_t *);
Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_AddWarnOptionUnicode(PyObject *);
Py_DEPRECATED(3.11) PyAPI_FUNC(int) PySys_HasWarnOptions(void);
Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_AddXOption(const wchar_t *);
PyAPI_FUNC(PyObject *) PySys_GetXOptions(void);
#if !defined(Py_LIMITED_API)

View file

@ -0,0 +1,17 @@
Remove the following old functions to configure the Python initialization,
deprecated in Python 3.11:
* ``PySys_AddWarnOptionUnicode()``
* ``PySys_AddWarnOption()``
* ``PySys_AddXOption()``
* ``PySys_HasWarnOptions()``
* ``PySys_SetArgvEx()``
* ``PySys_SetArgv()``
* ``PySys_SetPath()``
* ``Py_SetPath()``
* ``Py_SetProgramName()``
* ``Py_SetPythonHome()``
* ``Py_SetStandardStreamEncoding()``
* ``_Py_SetProgramFullPath()``
Patch by Victor Stinner.

View file

@ -1311,8 +1311,10 @@
added = '3.2'
[function.PySys_AddWarnOption]
added = '3.2'
abi_only = true
[function.PySys_AddWarnOptionUnicode]
added = '3.2'
abi_only = true
[function.PySys_FormatStderr]
added = '3.2'
[function.PySys_FormatStdout]
@ -1321,16 +1323,20 @@
added = '3.2'
[function.PySys_HasWarnOptions]
added = '3.2'
abi_only = true
[function.PySys_ResetWarnOptions]
added = '3.2'
[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]
added = '3.2'
abi_only = true
[function.PySys_WriteStderr]
added = '3.2'
[function.PySys_WriteStdout]
@ -1658,8 +1664,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]
@ -1990,6 +1998,7 @@
added = '3.7' # (and 3.6.1 and 3.5.3)
[function.PySys_AddXOption]
added = '3.7' # (and 3.6.1 and 3.5.3)
abi_only = true
[function.PySys_GetXOptions]
added = '3.7' # (and 3.6.1 and 3.5.3)
[function.PyUnicode_AsUCS4]
@ -2020,6 +2029,7 @@
added = '3.7' # (and 3.6.1 and 3.5.3)
[function.Py_SetPath]
added = '3.7' # (and 3.6.1 and 3.5.3)
abi_only = true
[function.PyErr_SetExcFromWindowsErr]
added = '3.7' # (and 3.6.1 and 3.5.3)
ifdef = 'MS_WINDOWS'

View file

@ -636,7 +636,6 @@ pymain_free(void)
remain valid after Py_Finalize(), since
Py_Initialize()-Py_Finalize() can be called multiple times. */
_PyPathConfig_ClearGlobal();
_Py_ClearStandardStreamEncoding();
_Py_ClearArgcArgv();
_PyRuntime_Finalize();
}

View file

@ -14,6 +14,15 @@
#include <stdlib.h> // putenv()
#include <wchar.h>
// These functions were removed from Python 3.13 API but are still exported
// for the stable ABI. We want to test them in this program.
extern void Py_SetProgramName(const wchar_t *program_name);
extern void PySys_AddWarnOption(const wchar_t *s);
extern void PySys_AddXOption(const wchar_t *s);
extern void Py_SetPath(const wchar_t *path);
extern void Py_SetPythonHome(const wchar_t *home);
int main_argc;
char **main_argv;
@ -204,23 +213,34 @@ static int test_repeated_simple_init(void)
* Test forcing a particular IO encoding
*****************************************************/
static void check_stdio_details(const char *encoding, const char * errors)
static void check_stdio_details(const wchar_t *encoding, const wchar_t *errors)
{
/* Output info for the test case to check */
if (encoding) {
printf("Expected encoding: %s\n", encoding);
printf("Expected encoding: %ls\n", encoding);
} else {
printf("Expected encoding: default\n");
}
if (errors) {
printf("Expected errors: %s\n", errors);
printf("Expected errors: %ls\n", errors);
} else {
printf("Expected errors: default\n");
}
fflush(stdout);
PyConfig config;
_PyConfig_InitCompatConfig(&config);
/* Force the given IO encoding */
Py_SetStandardStreamEncoding(encoding, errors);
_testembed_Py_InitializeFromConfig();
if (encoding) {
config_set_string(&config, &config.stdio_encoding, encoding);
}
if (errors) {
config_set_string(&config, &config.stdio_errors, errors);
}
config_set_program_name(&config);
init_from_config_clear(&config);
PyRun_SimpleString(
"import sys;"
"print('stdin: {0.encoding}:{0.errors}'.format(sys.stdin));"
@ -237,19 +257,11 @@ static int test_forced_io_encoding(void)
printf("--- Use defaults ---\n");
check_stdio_details(NULL, NULL);
printf("--- Set errors only ---\n");
check_stdio_details(NULL, "ignore");
check_stdio_details(NULL, L"ignore");
printf("--- Set encoding only ---\n");
check_stdio_details("iso8859-1", NULL);
check_stdio_details(L"iso8859-1", NULL);
printf("--- Set encoding and errors ---\n");
check_stdio_details("iso8859-1", "replace");
/* Check calling after initialization fails */
Py_Initialize();
if (Py_SetStandardStreamEncoding(NULL, NULL) == 0) {
printf("Unexpected success calling Py_SetStandardStreamEncoding");
}
Py_Finalize();
check_stdio_details(L"iso8859-1", L"replace");
return 0;
}
@ -639,11 +651,7 @@ static int test_init_from_config(void)
/* FIXME: test path config: module_search_path .. dll_path */
putenv("PYTHONPLATLIBDIR=env_platlibdir");
status = PyConfig_SetBytesString(&config, &config.platlibdir, "my_platlibdir");
if (PyStatus_Exception(status)) {
PyConfig_Clear(&config);
Py_ExitStatusException(status);
}
config_set_string(&config, &config.platlibdir, L"my_platlibdir");
putenv("PYTHONVERBOSE=0");
Py_VerboseFlag = 0;
@ -682,12 +690,6 @@ static int test_init_from_config(void)
config.buffered_stdio = 0;
putenv("PYTHONIOENCODING=cp424");
Py_SetStandardStreamEncoding("ascii", "ignore");
#ifdef MS_WINDOWS
/* Py_SetStandardStreamEncoding() sets Py_LegacyWindowsStdioFlag to 1.
Force it to 0 through the config. */
config.legacy_windows_stdio = 0;
#endif
config_set_string(&config, &config.stdio_encoding, L"iso8859-1");
config_set_string(&config, &config.stdio_errors, L"replace");
@ -1410,11 +1412,7 @@ static int test_init_read_set(void)
PyConfig config;
PyConfig_InitPythonConfig(&config);
status = PyConfig_SetBytesString(&config, &config.program_name,
"./init_read_set");
if (PyStatus_Exception(status)) {
goto fail;
}
config_set_string(&config, &config.program_name, L"./init_read_set");
status = PyConfig_Read(&config);
if (PyStatus_Exception(status)) {

View file

@ -514,94 +514,6 @@ _PyWideStringList_AsList(const PyWideStringList *list)
}
/* --- Py_SetStandardStreamEncoding() ----------------------------- */
/* Helper to allow an embedding application to override the normal
* mechanism that attempts to figure out an appropriate IO encoding
*/
static char *_Py_StandardStreamEncoding = NULL;
static char *_Py_StandardStreamErrors = NULL;
int
Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
{
if (Py_IsInitialized()) {
/* This is too late to have any effect */
return -1;
}
int res = 0;
/* Py_SetStandardStreamEncoding() can be called before Py_Initialize(),
but Py_Initialize() can change the allocator. Use a known allocator
to be able to release the memory later. */
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
/* Can't call PyErr_NoMemory() on errors, as Python hasn't been
* initialised yet.
*
* However, the raw memory allocators are initialised appropriately
* as C static variables, so _PyMem_RawStrdup is OK even though
* Py_Initialize hasn't been called yet.
*/
if (encoding) {
PyMem_RawFree(_Py_StandardStreamEncoding);
_Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding);
if (!_Py_StandardStreamEncoding) {
res = -2;
goto done;
}
}
if (errors) {
PyMem_RawFree(_Py_StandardStreamErrors);
_Py_StandardStreamErrors = _PyMem_RawStrdup(errors);
if (!_Py_StandardStreamErrors) {
PyMem_RawFree(_Py_StandardStreamEncoding);
_Py_StandardStreamEncoding = NULL;
res = -3;
goto done;
}
}
#ifdef MS_WINDOWS
if (_Py_StandardStreamEncoding) {
_Py_COMP_DIAG_PUSH
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
/* Overriding the stream encoding implies legacy streams */
Py_LegacyWindowsStdioFlag = 1;
_Py_COMP_DIAG_POP
}
#endif
done:
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
return res;
}
void
_Py_ClearStandardStreamEncoding(void)
{
/* Use the same allocator than Py_SetStandardStreamEncoding() */
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
/* We won't need them anymore. */
if (_Py_StandardStreamEncoding) {
PyMem_RawFree(_Py_StandardStreamEncoding);
_Py_StandardStreamEncoding = NULL;
}
if (_Py_StandardStreamErrors) {
PyMem_RawFree(_Py_StandardStreamErrors);
_Py_StandardStreamErrors = NULL;
}
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
}
/* --- Py_GetArgcArgv() ------------------------------------------- */
void
@ -1973,26 +1885,6 @@ config_init_stdio_encoding(PyConfig *config,
{
PyStatus status;
/* If Py_SetStandardStreamEncoding() has been called, use its
arguments if they are not NULL. */
if (config->stdio_encoding == NULL && _Py_StandardStreamEncoding != NULL) {
status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding,
_Py_StandardStreamEncoding,
"_Py_StandardStreamEncoding");
if (_PyStatus_EXCEPTION(status)) {
return status;
}
}
if (config->stdio_errors == NULL && _Py_StandardStreamErrors != NULL) {
status = CONFIG_SET_BYTES_STR(config, &config->stdio_errors,
_Py_StandardStreamErrors,
"_Py_StandardStreamErrors");
if (_PyStatus_EXCEPTION(status)) {
return status;
}
}
// Exit if encoding and errors are defined
if (config->stdio_encoding != NULL && config->stdio_errors != NULL) {
return _PyStatus_OK();

View file

@ -211,7 +211,8 @@ path_out_of_memory(const char *func)
_Py_FatalErrorFunc(func, "out of memory");
}
void
// Removed in Python 3.13 API, but kept for the stable ABI
PyAPI_FUNC(void)
Py_SetPath(const wchar_t *path)
{
if (path == NULL) {
@ -252,7 +253,8 @@ Py_SetPath(const wchar_t *path)
}
void
// Removed in Python 3.13 API, but kept for the stable ABI
PyAPI_FUNC(void)
Py_SetPythonHome(const wchar_t *home)
{
int has_value = home && home[0];
@ -275,7 +277,8 @@ Py_SetPythonHome(const wchar_t *home)
}
void
// Removed in Python 3.13 API, but kept for the stable ABI
PyAPI_FUNC(void)
Py_SetProgramName(const wchar_t *program_name)
{
int has_value = program_name && program_name[0];
@ -297,28 +300,6 @@ Py_SetProgramName(const wchar_t *program_name)
}
}
void
_Py_SetProgramFullPath(const wchar_t *program_full_path)
{
int has_value = program_full_path && program_full_path[0];
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
PyMem_RawFree(_Py_path_config.program_full_path);
_Py_path_config.program_full_path = NULL;
if (has_value) {
_Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
}
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (has_value && _Py_path_config.program_full_path == NULL) {
path_out_of_memory(__func__);
}
}
wchar_t *
Py_GetPath(void)

View file

@ -2556,7 +2556,6 @@ init_sys_streams(PyThreadState *tstate)
res = _PyStatus_ERR("can't initialize sys standard streams");
done:
_Py_ClearStandardStreamEncoding();
Py_XDECREF(iomod);
return res;
}

View file

@ -2614,7 +2614,8 @@ _PySys_AddWarnOptionWithError(PyThreadState *tstate, PyObject *option)
return 0;
}
void
// Removed in Python 3.13 API, but kept for the stable ABI
PyAPI_FUNC(void)
PySys_AddWarnOptionUnicode(PyObject *option)
{
PyThreadState *tstate = _PyThreadState_GET();
@ -2626,7 +2627,8 @@ PySys_AddWarnOptionUnicode(PyObject *option)
}
}
void
// Removed in Python 3.13 API, but kept for the stable ABI
PyAPI_FUNC(void)
PySys_AddWarnOption(const wchar_t *s)
{
PyThreadState *tstate = _PyThreadState_GET();
@ -2645,7 +2647,8 @@ _Py_COMP_DIAG_POP
Py_DECREF(unicode);
}
int
// Removed in Python 3.13 API, but kept for the stable ABI
PyAPI_FUNC(int)
PySys_HasWarnOptions(void)
{
PyThreadState *tstate = _PyThreadState_GET();
@ -2718,7 +2721,8 @@ _PySys_AddXOptionWithError(const wchar_t *s)
return -1;
}
void
// Removed in Python 3.13 API, but kept for the stable ABI
PyAPI_FUNC(void)
PySys_AddXOption(const wchar_t *s)
{
PyThreadState *tstate = _PyThreadState_GET();
@ -3621,7 +3625,8 @@ makepathobject(const wchar_t *path, wchar_t delim)
return v;
}
void
// Removed in Python 3.13 API, but kept for the stable ABI
PyAPI_FUNC(void)
PySys_SetPath(const wchar_t *path)
{
PyObject *v;
@ -3653,7 +3658,8 @@ make_sys_argv(int argc, wchar_t * const * argv)
return list;
}
void
// Removed in Python 3.13 API, but kept for the stable ABI
PyAPI_FUNC(void)
PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
{
wchar_t* empty_argv[1] = {L""};
@ -3697,7 +3703,8 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
}
}
void
// Removed in Python 3.13 API, but kept for the stable ABI
PyAPI_FUNC(void)
PySys_SetArgv(int argc, wchar_t **argv)
{
_Py_COMP_DIAG_PUSH