Python-checkins
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
January 2025
- 1 participants
- 532 discussions
https://github.com/python/cpython/commit/a42915979796565635dcfcd45d2b62b3e5…
commit: a42915979796565635dcfcd45d2b62b3e5e46eba
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-20T11:42:04+01:00
summary:
Reorganize the PyInitConfig documentation (#129047)
Document the new PyInitConfig API before the old PyConfig API.
files:
M Doc/c-api/init_config.rst
diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst
index 85566631ca1676..a549d4c55fc43d 100644
--- a/Doc/c-api/init_config.rst
+++ b/Doc/c-api/init_config.rst
@@ -6,28 +6,15 @@
Python Initialization Configuration
***********************************
-.. _pyconfig_api:
-
-PyConfig C API
-==============
-.. versionadded:: 3.8
-
-Python can be initialized with :c:func:`Py_InitializeFromConfig` and the
-:c:type:`PyConfig` structure. It can be preinitialized with
-:c:func:`Py_PreInitialize` and the :c:type:`PyPreConfig` structure.
+.. _pyinitconfig_api:
-There are two kinds of configuration:
+PyInitConfig C API
+==================
-* The :ref:`Python Configuration <init-python-config>` can be used to build a
- customized Python which behaves as the regular Python. For example,
- environment variables and command line arguments are used to configure
- Python.
+.. versionadded:: 3.14
-* The :ref:`Isolated Configuration <init-isolated-conf>` can be used to embed
- Python into an application. It isolates Python from the system. For example,
- environment variables are ignored, the LC_CTYPE locale is left unchanged and
- no signal handler is registered.
+Python can be initialized with :c:func:`Py_InitializeFromInitConfig`.
The :c:func:`Py_RunMain` function can be used to write a customized Python
program.
@@ -35,1906 +22,1920 @@ program.
See also :ref:`Initialization, Finalization, and Threads <initialization>`.
.. seealso::
- :pep:`587` "Python Initialization Configuration".
+ :pep:`741` "Python Configuration C API".
Example
-------
-Example of customized Python always running in isolated mode::
-
- int main(int argc, char **argv)
- {
- PyStatus status;
+Example of customized Python always running with the :ref:`Python Development
+Mode <devmode>` enabled; return ``-1`` on error:
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
- config.isolated = 1;
+.. code-block:: c
- /* Decode command line arguments.
- Implicitly preinitialize Python (in isolated mode). */
- status = PyConfig_SetBytesArgv(&config, argc, argv);
- if (PyStatus_Exception(status)) {
- goto exception;
+ int init_python(void)
+ {
+ PyInitConfig *config = PyInitConfig_Create();
+ if (config == NULL) {
+ printf("PYTHON INIT ERROR: memory allocation failed\n");
+ return -1;
}
- status = Py_InitializeFromConfig(&config);
- if (PyStatus_Exception(status)) {
- goto exception;
+ // Enable the Python Development Mode
+ if (PyInitConfig_SetInt(config, "dev_mode", 1) < 0) {
+ goto error;
}
- PyConfig_Clear(&config);
- return Py_RunMain();
+ // Initialize Python with the configuration
+ if (Py_InitializeFromInitConfig(config) < 0) {
+ goto error;
+ }
+ PyInitConfig_Free(config);
+ return 0;
- exception:
- PyConfig_Clear(&config);
- if (PyStatus_IsExit(status)) {
- return status.exitcode;
+ error:
+ {
+ // Display the error message.
+ //
+ // This uncommon braces style is used, because you cannot make
+ // goto targets point to variable declarations.
+ const char *err_msg;
+ (void)PyInitConfig_GetError(config, &err_msg);
+ printf("PYTHON INIT ERROR: %s\n", err_msg);
+ PyInitConfig_Free(config);
+ return -1;
}
- /* Display the error message and exit the process with
- non-zero exit code */
- Py_ExitStatusException(status);
}
+Create Config
+-------------
-PyWideStringList
-----------------
+.. c:struct:: PyInitConfig
-.. c:type:: PyWideStringList
+ Opaque structure to configure the Python initialization.
- List of ``wchar_t*`` strings.
- If *length* is non-zero, *items* must be non-``NULL`` and all strings must be
- non-``NULL``.
+.. c:function:: PyInitConfig* PyInitConfig_Create(void)
- .. c:namespace:: NULL
+ Create a new initialization configuration using :ref:`Isolated Configuration
+ <init-isolated-conf>` default values.
- Methods:
+ It must be freed by :c:func:`PyInitConfig_Free`.
- .. c:function:: PyStatus PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
+ Return ``NULL`` on memory allocation failure.
- Append *item* to *list*.
- Python must be preinitialized to call this function.
+.. c:function:: void PyInitConfig_Free(PyInitConfig *config)
- .. c:function:: PyStatus PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item)
+ Free memory of the initialization configuration *config*.
- Insert *item* into *list* at *index*.
+ If *config* is ``NULL``, no operation is performed.
- If *index* is greater than or equal to *list* length, append *item* to
- *list*.
- *index* must be greater than or equal to ``0``.
+Error Handling
+--------------
- Python must be preinitialized to call this function.
+.. c:function:: int PyInitConfig_GetError(PyInitConfig* config, const char **err_msg)
- .. c:namespace:: PyWideStringList
+ Get the *config* error message.
- Structure fields:
+ * Set *\*err_msg* and return ``1`` if an error is set.
+ * Set *\*err_msg* to ``NULL`` and return ``0`` otherwise.
- .. c:member:: Py_ssize_t length
+ An error message is an UTF-8 encoded string.
- List length.
+ If *config* has an exit code, format the exit code as an error
+ message.
- .. c:member:: wchar_t** items
+ The error message remains valid until another ``PyInitConfig``
+ function is called with *config*. The caller doesn't have to free the
+ error message.
- List items.
-PyStatus
---------
+.. c:function:: int PyInitConfig_GetExitCode(PyInitConfig* config, int *exitcode)
-.. c:type:: PyStatus
+ Get the *config* exit code.
- Structure to store an initialization function status: success, error
- or exit.
+ * Set *\*exitcode* and return ``1`` if *config* has an exit code set.
+ * Return ``0`` if *config* has no exit code set.
- For an error, it can store the C function name which created the error.
+ Only the ``Py_InitializeFromInitConfig()`` function can set an exit
+ code if the ``parse_argv`` option is non-zero.
- Structure fields:
+ 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``).
- .. c:member:: int exitcode
- Exit code. Argument passed to ``exit()``.
+Get Options
+-----------
- .. c:member:: const char *err_msg
+The configuration option *name* parameter must be a non-NULL
+null-terminated UTF-8 encoded string.
- Error message.
+.. c:function:: int PyInitConfig_HasOption(PyInitConfig *config, const char *name)
- .. c:member:: const char *func
+ Test if the configuration has an option called *name*.
- Name of the function which created an error, can be ``NULL``.
+ Return ``1`` if the option exists, or return ``0`` otherwise.
- .. c:namespace:: NULL
- Functions to create a status:
+.. c:function:: int PyInitConfig_GetInt(PyInitConfig *config, const char *name, int64_t *value)
- .. c:function:: PyStatus PyStatus_Ok(void)
+ Get an integer configuration option.
- Success.
+ * Set *\*value*, and return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
- .. c:function:: PyStatus PyStatus_Error(const char *err_msg)
- Initialization error with a message.
+.. c:function:: int PyInitConfig_GetStr(PyInitConfig *config, const char *name, char **value)
- *err_msg* must not be ``NULL``.
+ Get a string configuration option as a null-terminated UTF-8
+ encoded string.
- .. c:function:: PyStatus PyStatus_NoMemory(void)
+ * Set *\*value*, and return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
- Memory allocation failure (out of memory).
+ *\*value* can be set to ``NULL`` if the option is an optional string and the
+ option is unset.
- .. c:function:: PyStatus PyStatus_Exit(int exitcode)
+ On success, the string must be released with ``free(value)`` if it's not
+ ``NULL``.
- Exit Python with the specified exit code.
- Functions to handle a status:
+.. c:function:: int PyInitConfig_GetStrList(PyInitConfig *config, const char *name, size_t *length, char ***items)
- .. c:function:: int PyStatus_Exception(PyStatus status)
+ Get a string list configuration option as an array of
+ null-terminated UTF-8 encoded strings.
- Is the status an error or an exit? If true, the exception must be
- handled; by calling :c:func:`Py_ExitStatusException` for example.
+ * Set *\*length* and *\*value*, and return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
- .. c:function:: int PyStatus_IsError(PyStatus status)
+ On success, the string list must be released with
+ ``PyInitConfig_FreeStrList(length, items)``.
- Is the result an error?
- .. c:function:: int PyStatus_IsExit(PyStatus status)
+.. c:function:: void PyInitConfig_FreeStrList(size_t length, char **items)
- Is the result an exit?
+ Free memory of a string list created by
+ ``PyInitConfig_GetStrList()``.
- .. c:function:: void Py_ExitStatusException(PyStatus status)
- Call ``exit(exitcode)`` if *status* is an exit. Print the error
- message and exit with a non-zero exit code if *status* is an error. Must
- only be called if ``PyStatus_Exception(status)`` is non-zero.
+Set Options
+-----------
-.. note::
- Internally, Python uses macros which set ``PyStatus.func``,
- whereas functions to create a status set ``func`` to ``NULL``.
+The configuration option *name* parameter must be a non-NULL null-terminated
+UTF-8 encoded string.
-Example::
+Some configuration options have side effects on other options. This logic is
+only implemented when ``Py_InitializeFromInitConfig()`` is called, not by the
+"Set" functions below. For example, setting ``dev_mode`` to ``1`` does not set
+``faulthandler`` to ``1``.
- PyStatus alloc(void **ptr, size_t size)
- {
- *ptr = PyMem_RawMalloc(size);
- if (*ptr == NULL) {
- return PyStatus_NoMemory();
- }
- return PyStatus_Ok();
- }
+.. c:function:: int PyInitConfig_SetInt(PyInitConfig *config, const char *name, int64_t value)
- int main(int argc, char **argv)
- {
- void *ptr;
- PyStatus status = alloc(&ptr, 16);
- if (PyStatus_Exception(status)) {
- Py_ExitStatusException(status);
- }
- PyMem_Free(ptr);
- return 0;
- }
+ Set an integer configuration option.
+ * Return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
-PyPreConfig
------------
-.. c:type:: PyPreConfig
+.. c:function:: int PyInitConfig_SetStr(PyInitConfig *config, const char *name, const char *value)
- Structure used to preinitialize Python.
+ Set a string configuration option from a null-terminated UTF-8
+ encoded string. The string is copied.
- .. c:namespace:: NULL
+ * Return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
- Function to initialize a preconfiguration:
- .. c:function:: void PyPreConfig_InitPythonConfig(PyPreConfig *preconfig)
+.. c:function:: int PyInitConfig_SetStrList(PyInitConfig *config, const char *name, size_t length, char * const *items)
- Initialize the preconfiguration with :ref:`Python Configuration
- <init-python-config>`.
+ Set a string list configuration option from an array of
+ null-terminated UTF-8 encoded strings. The string list is copied.
- .. c:function:: void PyPreConfig_InitIsolatedConfig(PyPreConfig *preconfig)
+ * Return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
- Initialize the preconfiguration with :ref:`Isolated Configuration
- <init-isolated-conf>`.
- .. c:namespace:: PyPreConfig
+Module
+------
- Structure fields:
+.. c:function:: int PyInitConfig_AddModule(PyInitConfig *config, const char *name, PyObject* (*initfunc)(void))
- .. c:member:: int allocator
-
- Name of the Python memory allocators:
+ Add a built-in extension module to the table of built-in modules.
- * ``PYMEM_ALLOCATOR_NOT_SET`` (``0``): don't change memory allocators
- (use defaults).
- * ``PYMEM_ALLOCATOR_DEFAULT`` (``1``): :ref:`default memory allocators
- <default-memory-allocators>`.
- * ``PYMEM_ALLOCATOR_DEBUG`` (``2``): :ref:`default memory allocators
- <default-memory-allocators>` with :ref:`debug hooks
- <pymem-debug-hooks>`.
- * ``PYMEM_ALLOCATOR_MALLOC`` (``3``): use ``malloc()`` of the C library.
- * ``PYMEM_ALLOCATOR_MALLOC_DEBUG`` (``4``): force usage of
- ``malloc()`` with :ref:`debug hooks <pymem-debug-hooks>`.
- * ``PYMEM_ALLOCATOR_PYMALLOC`` (``5``): :ref:`Python pymalloc memory
- allocator <pymalloc>`.
- * ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` (``6``): :ref:`Python pymalloc
- memory allocator <pymalloc>` with :ref:`debug hooks
- <pymem-debug-hooks>`.
- * ``PYMEM_ALLOCATOR_MIMALLOC`` (``6``): use ``mimalloc``, a fast
- malloc replacement.
- * ``PYMEM_ALLOCATOR_MIMALLOC_DEBUG`` (``7``): use ``mimalloc``, a fast
- malloc replacement with :ref:`debug hooks <pymem-debug-hooks>`.
+ The new module can be imported by the name *name*, and uses the function
+ *initfunc* as the initialization function called on the first attempted
+ import.
+ * Return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
- ``PYMEM_ALLOCATOR_PYMALLOC`` and ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` are
- not supported if Python is :option:`configured using --without-pymalloc
- <--without-pymalloc>`.
+ If Python is initialized multiple times, ``PyInitConfig_AddModule()`` must
+ be called at each Python initialization.
- ``PYMEM_ALLOCATOR_MIMALLOC`` and ``PYMEM_ALLOCATOR_MIMALLOC_DEBUG`` are
- not supported if Python is :option:`configured using --without-mimalloc
- <--without-mimalloc>` or if the underlying atomic support isn't
- available.
+ Similar to the :c:func:`PyImport_AppendInittab` function.
- See :ref:`Memory Management <memory>`.
- Default: ``PYMEM_ALLOCATOR_NOT_SET``.
+Initialize Python
+-----------------
- .. c:member:: int configure_locale
+.. c:function:: int Py_InitializeFromInitConfig(PyInitConfig *config)
- Set the LC_CTYPE locale to the user preferred locale.
+ Initialize Python from the initialization configuration.
- If equals to ``0``, set :c:member:`~PyPreConfig.coerce_c_locale` and
- :c:member:`~PyPreConfig.coerce_c_locale_warn` members to ``0``.
+ * 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 the :term:`locale encoding`.
+ See ``PyInitConfig_GetExitcode()`` for the exit code case.
- Default: ``1`` in Python config, ``0`` in isolated config.
- .. c:member:: int coerce_c_locale
+Runtime Python configuration API
+================================
- If equals to ``2``, coerce the C locale.
+At runtime, it's possible to get and set configuration options using
+:c:func:`PyConfig_Get` and :c:func:`PyConfig_Set` functions.
- If equals to ``1``, read the LC_CTYPE locale to decide if it should be
- coerced.
+The configuration option *name* parameter must be a non-NULL null-terminated
+UTF-8 encoded string.
- See the :term:`locale encoding`.
+Some options are read from the :mod:`sys` attributes. For example, the option
+``"argv"`` is read from :data:`sys.argv`.
- Default: ``-1`` in Python config, ``0`` in isolated config.
- .. c:member:: int coerce_c_locale_warn
+.. c:function:: PyObject* PyConfig_Get(const char *name)
- If non-zero, emit a warning if the C locale is coerced.
+ Get the current runtime value of a configuration option as a Python object.
- Default: ``-1`` in Python config, ``0`` in isolated config.
+ * Return a new reference on success.
+ * Set an exception and return ``NULL`` on error.
- .. c:member:: int dev_mode
+ The object type depends on the configuration option. It can be:
- :ref:`Python Development Mode <devmode>`: see
- :c:member:`PyConfig.dev_mode`.
+ * ``bool``
+ * ``int``
+ * ``str``
+ * ``list[str]``
+ * ``dict[str, str]``
- Default: ``-1`` in Python mode, ``0`` in isolated mode.
+ The caller must hold the GIL. The function cannot be called before
+ Python initialization nor after Python finalization.
- .. c:member:: int isolated
+ .. versionadded:: 3.14
- Isolated mode: see :c:member:`PyConfig.isolated`.
- Default: ``0`` in Python mode, ``1`` in isolated mode.
+.. c:function:: int PyConfig_GetInt(const char *name, int *value)
- .. c:member:: int legacy_windows_fs_encoding
+ Similar to :c:func:`PyConfig_Get`, but get the value as a C int.
- If non-zero:
+ * Return ``0`` on success.
+ * Set an exception and return ``-1`` on error.
- * Set :c:member:`PyPreConfig.utf8_mode` to ``0``,
- * Set :c:member:`PyConfig.filesystem_encoding` to ``"mbcs"``,
- * Set :c:member:`PyConfig.filesystem_errors` to ``"replace"``.
+ .. versionadded:: 3.14
- Initialized from the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment
- variable value.
- Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
- Windows specific code.
+.. c:function:: PyObject* PyConfig_Names(void)
- Default: ``0``.
+ Get all configuration option names as a ``frozenset``.
- .. c:member:: int parse_argv
+ * Return a new reference on success.
+ * Set an exception and return ``NULL`` on error.
- If non-zero, :c:func:`Py_PreInitializeFromArgs` and
- :c:func:`Py_PreInitializeFromBytesArgs` parse their ``argv`` argument the
- same way the regular Python parses command line arguments: see
- :ref:`Command Line Arguments <using-on-cmdline>`.
+ The caller must hold the GIL. The function cannot be called before
+ Python initialization nor after Python finalization.
- Default: ``1`` in Python config, ``0`` in isolated config.
+ .. versionadded:: 3.14
- .. c:member:: int use_environment
- Use :ref:`environment variables <using-on-envvars>`? See
- :c:member:`PyConfig.use_environment`.
+.. c:function:: int PyConfig_Set(const char *name, PyObject *value)
- Default: ``1`` in Python config and ``0`` in isolated config.
+ Set the current runtime value of a configuration option.
- .. c:member:: int utf8_mode
+ * Raise a :exc:`ValueError` if there is no option *name*.
+ * Raise a :exc:`ValueError` if *value* is an invalid value.
+ * Raise a :exc:`ValueError` if the option is read-only (cannot be set).
+ * Raise a :exc:`TypeError` if *value* has not the proper type.
- If non-zero, enable the :ref:`Python UTF-8 Mode <utf8-mode>`.
+ The caller must hold the GIL. The function cannot be called before
+ Python initialization nor after Python finalization.
- Set to ``0`` or ``1`` by the :option:`-X utf8 <-X>` command line option
- and the :envvar:`PYTHONUTF8` environment variable.
+ .. versionadded:: 3.14
- Also set to ``1`` if the ``LC_CTYPE`` locale is ``C`` or ``POSIX``.
- Default: ``-1`` in Python config and ``0`` in isolated config.
+.. _pyconfig_api:
+PyConfig C API
+==============
-.. _c-preinit:
+.. versionadded:: 3.8
-Preinitialize Python with PyPreConfig
--------------------------------------
+Python can be initialized with :c:func:`Py_InitializeFromConfig` and the
+:c:type:`PyConfig` structure. It can be preinitialized with
+:c:func:`Py_PreInitialize` and the :c:type:`PyPreConfig` structure.
-The preinitialization of Python:
+There are two kinds of configuration:
-* Set the Python memory allocators (:c:member:`PyPreConfig.allocator`)
-* Configure the LC_CTYPE locale (:term:`locale encoding`)
-* Set the :ref:`Python UTF-8 Mode <utf8-mode>`
- (:c:member:`PyPreConfig.utf8_mode`)
+* The :ref:`Python Configuration <init-python-config>` can be used to build a
+ customized Python which behaves as the regular Python. For example,
+ environment variables and command line arguments are used to configure
+ Python.
-The current preconfiguration (``PyPreConfig`` type) is stored in
-``_PyRuntime.preconfig``.
+* The :ref:`Isolated Configuration <init-isolated-conf>` can be used to embed
+ Python into an application. It isolates Python from the system. For example,
+ environment variables are ignored, the LC_CTYPE locale is left unchanged and
+ no signal handler is registered.
-Functions to preinitialize Python:
+The :c:func:`Py_RunMain` function can be used to write a customized Python
+program.
-.. c:function:: PyStatus Py_PreInitialize(const PyPreConfig *preconfig)
+See also :ref:`Initialization, Finalization, and Threads <initialization>`.
- Preinitialize Python from *preconfig* preconfiguration.
+.. seealso::
+ :pep:`587` "Python Initialization Configuration".
- *preconfig* must not be ``NULL``.
-.. c:function:: PyStatus Py_PreInitializeFromBytesArgs(const PyPreConfig *preconfig, int argc, char * const *argv)
+Example
+-------
- Preinitialize Python from *preconfig* preconfiguration.
+Example of customized Python always running in isolated mode::
- Parse *argv* command line arguments (bytes strings) if
- :c:member:`~PyPreConfig.parse_argv` of *preconfig* is non-zero.
+ int main(int argc, char **argv)
+ {
+ PyStatus status;
- *preconfig* must not be ``NULL``.
+ PyConfig config;
+ PyConfig_InitPythonConfig(&config);
+ config.isolated = 1;
-.. c:function:: PyStatus Py_PreInitializeFromArgs(const PyPreConfig *preconfig, int argc, wchar_t * const * argv)
+ /* Decode command line arguments.
+ Implicitly preinitialize Python (in isolated mode). */
+ status = PyConfig_SetBytesArgv(&config, argc, argv);
+ if (PyStatus_Exception(status)) {
+ goto exception;
+ }
- Preinitialize Python from *preconfig* preconfiguration.
+ status = Py_InitializeFromConfig(&config);
+ if (PyStatus_Exception(status)) {
+ goto exception;
+ }
+ PyConfig_Clear(&config);
- Parse *argv* command line arguments (wide strings) if
- :c:member:`~PyPreConfig.parse_argv` of *preconfig* is non-zero.
+ return Py_RunMain();
- *preconfig* must not be ``NULL``.
+ 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);
+ }
-The caller is responsible to handle exceptions (error or exit) using
-:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`.
-For :ref:`Python Configuration <init-python-config>`
-(:c:func:`PyPreConfig_InitPythonConfig`), if Python is initialized with
-command line arguments, the command line arguments must also be passed to
-preinitialize Python, since they have an effect on the pre-configuration
-like encodings. For example, the :option:`-X utf8 <-X>` command line option
-enables the :ref:`Python UTF-8 Mode <utf8-mode>`.
+PyWideStringList
+----------------
-``PyMem_SetAllocator()`` can be called after :c:func:`Py_PreInitialize` and
-before :c:func:`Py_InitializeFromConfig` to install a custom memory allocator.
-It can be called before :c:func:`Py_PreInitialize` if
-:c:member:`PyPreConfig.allocator` is set to ``PYMEM_ALLOCATOR_NOT_SET``.
+.. c:type:: PyWideStringList
-Python memory allocation functions like :c:func:`PyMem_RawMalloc` must not be
-used before the Python preinitialization, whereas calling directly ``malloc()``
-and ``free()`` is always safe. :c:func:`Py_DecodeLocale` must not be called
-before the Python preinitialization.
+ List of ``wchar_t*`` strings.
-Example using the preinitialization to enable
-the :ref:`Python UTF-8 Mode <utf8-mode>`::
+ If *length* is non-zero, *items* must be non-``NULL`` and all strings must be
+ non-``NULL``.
- PyStatus status;
- PyPreConfig preconfig;
- PyPreConfig_InitPythonConfig(&preconfig);
+ .. c:namespace:: NULL
- preconfig.utf8_mode = 1;
+ Methods:
- status = Py_PreInitialize(&preconfig);
- if (PyStatus_Exception(status)) {
- Py_ExitStatusException(status);
- }
+ .. c:function:: PyStatus PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
- /* at this point, Python speaks UTF-8 */
+ Append *item* to *list*.
- Py_Initialize();
- /* ... use Python API here ... */
- Py_Finalize();
+ Python must be preinitialized to call this function.
+ .. c:function:: PyStatus PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item)
-PyConfig
---------
+ Insert *item* into *list* at *index*.
-.. c:type:: PyConfig
+ If *index* is greater than or equal to *list* length, append *item* to
+ *list*.
- Structure containing most parameters to configure Python.
+ *index* must be greater than or equal to ``0``.
- When done, the :c:func:`PyConfig_Clear` function must be used to release the
- configuration memory.
+ Python must be preinitialized to call this function.
- .. c:namespace:: NULL
+ .. c:namespace:: PyWideStringList
- Structure methods:
+ Structure fields:
- .. c:function:: void PyConfig_InitPythonConfig(PyConfig *config)
+ .. c:member:: Py_ssize_t length
- Initialize configuration with the :ref:`Python Configuration
- <init-python-config>`.
+ List length.
- .. c:function:: void PyConfig_InitIsolatedConfig(PyConfig *config)
+ .. c:member:: wchar_t** items
- Initialize configuration with the :ref:`Isolated Configuration
- <init-isolated-conf>`.
+ List items.
- .. c:function:: PyStatus PyConfig_SetString(PyConfig *config, wchar_t * const *config_str, const wchar_t *str)
+PyStatus
+--------
- Copy the wide character string *str* into ``*config_str``.
+.. c:type:: PyStatus
- :ref:`Preinitialize Python <c-preinit>` if needed.
+ Structure to store an initialization function status: success, error
+ or exit.
- .. c:function:: PyStatus PyConfig_SetBytesString(PyConfig *config, wchar_t * const *config_str, const char *str)
+ For an error, it can store the C function name which created the error.
- Decode *str* using :c:func:`Py_DecodeLocale` and set the result into
- ``*config_str``.
+ Structure fields:
- :ref:`Preinitialize Python <c-preinit>` if needed.
+ .. c:member:: int exitcode
- .. c:function:: PyStatus PyConfig_SetArgv(PyConfig *config, int argc, wchar_t * const *argv)
+ Exit code. Argument passed to ``exit()``.
- Set command line arguments (:c:member:`~PyConfig.argv` member of
- *config*) from the *argv* list of wide character strings.
+ .. c:member:: const char *err_msg
- :ref:`Preinitialize Python <c-preinit>` if needed.
+ Error message.
- .. c:function:: PyStatus PyConfig_SetBytesArgv(PyConfig *config, int argc, char * const *argv)
+ .. c:member:: const char *func
- Set command line arguments (:c:member:`~PyConfig.argv` member of
- *config*) from the *argv* list of bytes strings. Decode bytes using
- :c:func:`Py_DecodeLocale`.
+ Name of the function which created an error, can be ``NULL``.
- :ref:`Preinitialize Python <c-preinit>` if needed.
+ .. c:namespace:: NULL
- .. c:function:: PyStatus PyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list, Py_ssize_t length, wchar_t **items)
+ Functions to create a status:
- Set the list of wide strings *list* to *length* and *items*.
+ .. c:function:: PyStatus PyStatus_Ok(void)
- :ref:`Preinitialize Python <c-preinit>` if needed.
+ Success.
- .. c:function:: PyStatus PyConfig_Read(PyConfig *config)
+ .. c:function:: PyStatus PyStatus_Error(const char *err_msg)
- Read all Python configuration.
+ Initialization error with a message.
- Fields which are already initialized are left unchanged.
+ *err_msg* must not be ``NULL``.
- Fields for :ref:`path configuration <init-path-config>` are no longer
- calculated or modified when calling this function, as of Python 3.11.
+ .. c:function:: PyStatus PyStatus_NoMemory(void)
- The :c:func:`PyConfig_Read` function only parses
- :c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv`
- is set to ``2`` after arguments are parsed. Since Python arguments are
- stripped from :c:member:`PyConfig.argv`, parsing arguments twice would
- parse the application options as Python options.
+ Memory allocation failure (out of memory).
- :ref:`Preinitialize Python <c-preinit>` if needed.
+ .. c:function:: PyStatus PyStatus_Exit(int exitcode)
- .. versionchanged:: 3.10
- The :c:member:`PyConfig.argv` arguments are now only parsed once,
- :c:member:`PyConfig.parse_argv` is set to ``2`` after arguments are
- parsed, and arguments are only parsed if
- :c:member:`PyConfig.parse_argv` equals ``1``.
+ Exit Python with the specified exit code.
- .. versionchanged:: 3.11
- :c:func:`PyConfig_Read` no longer calculates all paths, and so fields
- listed under :ref:`Python Path Configuration <init-path-config>` may
- no longer be updated until :c:func:`Py_InitializeFromConfig` is
- called.
+ Functions to handle a status:
- .. c:function:: void PyConfig_Clear(PyConfig *config)
+ .. c:function:: int PyStatus_Exception(PyStatus status)
- Release configuration memory.
+ Is the status an error or an exit? If true, the exception must be
+ handled; by calling :c:func:`Py_ExitStatusException` for example.
- Most ``PyConfig`` methods :ref:`preinitialize Python <c-preinit>` if needed.
- In that case, the Python preinitialization configuration
- (:c:type:`PyPreConfig`) in based on the :c:type:`PyConfig`. If configuration
- fields which are in common with :c:type:`PyPreConfig` are tuned, they must
- be set before calling a :c:type:`PyConfig` method:
+ .. c:function:: int PyStatus_IsError(PyStatus status)
- * :c:member:`PyConfig.dev_mode`
- * :c:member:`PyConfig.isolated`
- * :c:member:`PyConfig.parse_argv`
- * :c:member:`PyConfig.use_environment`
+ Is the result an error?
- Moreover, if :c:func:`PyConfig_SetArgv` or :c:func:`PyConfig_SetBytesArgv`
- is used, this method must be called before other methods, since the
- preinitialization configuration depends on command line arguments (if
- :c:member:`~PyConfig.parse_argv` is non-zero).
+ .. c:function:: int PyStatus_IsExit(PyStatus status)
- The caller of these methods is responsible to handle exceptions (error or
- exit) using ``PyStatus_Exception()`` and ``Py_ExitStatusException()``.
+ Is the result an exit?
- .. c:namespace:: PyConfig
+ .. c:function:: void Py_ExitStatusException(PyStatus status)
- Structure fields:
+ Call ``exit(exitcode)`` if *status* is an exit. Print the error
+ message and exit with a non-zero exit code if *status* is an error. Must
+ only be called if ``PyStatus_Exception(status)`` is non-zero.
- .. c:member:: PyWideStringList argv
+.. note::
+ Internally, Python uses macros which set ``PyStatus.func``,
+ whereas functions to create a status set ``func`` to ``NULL``.
- .. index::
- single: main()
- single: argv (in module sys)
+Example::
- 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.
+ PyStatus alloc(void **ptr, size_t size)
+ {
+ *ptr = PyMem_RawMalloc(size);
+ if (*ptr == NULL) {
+ return PyStatus_NoMemory();
+ }
+ return PyStatus_Ok();
+ }
- Set :c:member:`~PyConfig.parse_argv` to ``1`` to parse
- :c:member:`~PyConfig.argv` the same way the regular Python parses Python
- command line arguments and then to strip Python arguments from
- :c:member:`~PyConfig.argv`.
+ int main(int argc, char **argv)
+ {
+ void *ptr;
+ PyStatus status = alloc(&ptr, 16);
+ if (PyStatus_Exception(status)) {
+ Py_ExitStatusException(status);
+ }
+ PyMem_Free(ptr);
+ return 0;
+ }
- If :c:member:`~PyConfig.argv` is empty, an empty string is added to
- ensure that :data:`sys.argv` always exists and is never empty.
- Default: ``NULL``.
+PyPreConfig
+-----------
- See also the :c:member:`~PyConfig.orig_argv` member.
+.. c:type:: PyPreConfig
- .. c:member:: int safe_path
+ Structure used to preinitialize Python.
- If equals to zero, ``Py_RunMain()`` prepends a potentially unsafe path to
- :data:`sys.path` at startup:
+ .. c:namespace:: NULL
- * If :c:member:`argv[0] <PyConfig.argv>` is equal to ``L"-m"``
- (``python -m module``), prepend the current working directory.
- * If running a script (``python script.py``), prepend the script's
- directory. If it's a symbolic link, resolve symbolic links.
- * Otherwise (``python -c code`` and ``python``), prepend an empty string,
- which means the current working directory.
+ Function to initialize a preconfiguration:
- Set to ``1`` by the :option:`-P` command line option and the
- :envvar:`PYTHONSAFEPATH` environment variable.
+ .. c:function:: void PyPreConfig_InitPythonConfig(PyPreConfig *preconfig)
- Default: ``0`` in Python config, ``1`` in isolated config.
+ Initialize the preconfiguration with :ref:`Python Configuration
+ <init-python-config>`.
- .. versionadded:: 3.11
+ .. c:function:: void PyPreConfig_InitIsolatedConfig(PyPreConfig *preconfig)
- .. c:member:: wchar_t* base_exec_prefix
+ Initialize the preconfiguration with :ref:`Isolated Configuration
+ <init-isolated-conf>`.
- :data:`sys.base_exec_prefix`.
+ .. c:namespace:: PyPreConfig
- Default: ``NULL``.
+ Structure fields:
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+ .. c:member:: int allocator
- See also :c:member:`PyConfig.exec_prefix`.
+ Name of the Python memory allocators:
- .. c:member:: wchar_t* base_executable
+ * ``PYMEM_ALLOCATOR_NOT_SET`` (``0``): don't change memory allocators
+ (use defaults).
+ * ``PYMEM_ALLOCATOR_DEFAULT`` (``1``): :ref:`default memory allocators
+ <default-memory-allocators>`.
+ * ``PYMEM_ALLOCATOR_DEBUG`` (``2``): :ref:`default memory allocators
+ <default-memory-allocators>` with :ref:`debug hooks
+ <pymem-debug-hooks>`.
+ * ``PYMEM_ALLOCATOR_MALLOC`` (``3``): use ``malloc()`` of the C library.
+ * ``PYMEM_ALLOCATOR_MALLOC_DEBUG`` (``4``): force usage of
+ ``malloc()`` with :ref:`debug hooks <pymem-debug-hooks>`.
+ * ``PYMEM_ALLOCATOR_PYMALLOC`` (``5``): :ref:`Python pymalloc memory
+ allocator <pymalloc>`.
+ * ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` (``6``): :ref:`Python pymalloc
+ memory allocator <pymalloc>` with :ref:`debug hooks
+ <pymem-debug-hooks>`.
+ * ``PYMEM_ALLOCATOR_MIMALLOC`` (``6``): use ``mimalloc``, a fast
+ malloc replacement.
+ * ``PYMEM_ALLOCATOR_MIMALLOC_DEBUG`` (``7``): use ``mimalloc``, a fast
+ malloc replacement with :ref:`debug hooks <pymem-debug-hooks>`.
- Python base executable: :data:`sys._base_executable`.
- Set by the :envvar:`__PYVENV_LAUNCHER__` environment variable.
+ ``PYMEM_ALLOCATOR_PYMALLOC`` and ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` are
+ not supported if Python is :option:`configured using --without-pymalloc
+ <--without-pymalloc>`.
- Set from :c:member:`PyConfig.executable` if ``NULL``.
+ ``PYMEM_ALLOCATOR_MIMALLOC`` and ``PYMEM_ALLOCATOR_MIMALLOC_DEBUG`` are
+ not supported if Python is :option:`configured using --without-mimalloc
+ <--without-mimalloc>` or if the underlying atomic support isn't
+ available.
- Default: ``NULL``.
+ See :ref:`Memory Management <memory>`.
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+ Default: ``PYMEM_ALLOCATOR_NOT_SET``.
- See also :c:member:`PyConfig.executable`.
+ .. c:member:: int configure_locale
- .. c:member:: wchar_t* base_prefix
+ Set the LC_CTYPE locale to the user preferred locale.
- :data:`sys.base_prefix`.
+ If equals to ``0``, set :c:member:`~PyPreConfig.coerce_c_locale` and
+ :c:member:`~PyPreConfig.coerce_c_locale_warn` members to ``0``.
- Default: ``NULL``.
+ See the :term:`locale encoding`.
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+ Default: ``1`` in Python config, ``0`` in isolated config.
- See also :c:member:`PyConfig.prefix`.
+ .. c:member:: int coerce_c_locale
- .. c:member:: int buffered_stdio
+ If equals to ``2``, coerce the C locale.
- If equals to ``0`` and :c:member:`~PyConfig.configure_c_stdio` is non-zero,
- disable buffering on the C streams stdout and stderr.
+ If equals to ``1``, read the LC_CTYPE locale to decide if it should be
+ coerced.
- Set to ``0`` by the :option:`-u` command line option and the
- :envvar:`PYTHONUNBUFFERED` environment variable.
+ See the :term:`locale encoding`.
- stdin is always opened in buffered mode.
+ Default: ``-1`` in Python config, ``0`` in isolated config.
- Default: ``1``.
+ .. c:member:: int coerce_c_locale_warn
- .. c:member:: int bytes_warning
+ If non-zero, emit a warning if the C locale is coerced.
- If equals to ``1``, issue a warning when comparing :class:`bytes` or
- :class:`bytearray` with :class:`str`, or comparing :class:`bytes` with
- :class:`int`.
-
- If equal or greater to ``2``, raise a :exc:`BytesWarning` exception in these
- cases.
-
- Incremented by the :option:`-b` command line option.
+ Default: ``-1`` in Python config, ``0`` in isolated config.
- Default: ``0``.
+ .. c:member:: int dev_mode
- .. c:member:: int warn_default_encoding
+ :ref:`Python Development Mode <devmode>`: see
+ :c:member:`PyConfig.dev_mode`.
- If non-zero, emit a :exc:`EncodingWarning` warning when :class:`io.TextIOWrapper`
- uses its default encoding. See :ref:`io-encoding-warning` for details.
+ Default: ``-1`` in Python mode, ``0`` in isolated mode.
- Default: ``0``.
+ .. c:member:: int isolated
- .. versionadded:: 3.10
+ Isolated mode: see :c:member:`PyConfig.isolated`.
- .. c:member:: int code_debug_ranges
+ Default: ``0`` in Python mode, ``1`` in isolated mode.
- If equals to ``0``, disables the inclusion of the end line and column
- mappings in code objects. Also disables traceback printing carets to
- specific error locations.
+ .. c:member:: int legacy_windows_fs_encoding
- Set to ``0`` by the :envvar:`PYTHONNODEBUGRANGES` environment variable
- and by the :option:`-X no_debug_ranges <-X>` command line option.
+ If non-zero:
- Default: ``1``.
+ * Set :c:member:`PyPreConfig.utf8_mode` to ``0``,
+ * Set :c:member:`PyConfig.filesystem_encoding` to ``"mbcs"``,
+ * Set :c:member:`PyConfig.filesystem_errors` to ``"replace"``.
- .. versionadded:: 3.11
+ Initialized from the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment
+ variable value.
- .. c:member:: wchar_t* check_hash_pycs_mode
+ Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
+ Windows specific code.
- Control the validation behavior of hash-based ``.pyc`` files:
- value of the :option:`--check-hash-based-pycs` command line option.
+ Default: ``0``.
- Valid values:
+ .. c:member:: int parse_argv
- - ``L"always"``: Hash the source file for invalidation regardless of
- value of the 'check_source' flag.
- - ``L"never"``: Assume that hash-based pycs always are valid.
- - ``L"default"``: The 'check_source' flag in hash-based pycs
- determines invalidation.
+ If non-zero, :c:func:`Py_PreInitializeFromArgs` and
+ :c:func:`Py_PreInitializeFromBytesArgs` parse their ``argv`` argument the
+ same way the regular Python parses command line arguments: see
+ :ref:`Command Line Arguments <using-on-cmdline>`.
- Default: ``L"default"``.
+ Default: ``1`` in Python config, ``0`` in isolated config.
- See also :pep:`552` "Deterministic pycs".
+ .. c:member:: int use_environment
- .. c:member:: int configure_c_stdio
+ Use :ref:`environment variables <using-on-envvars>`? See
+ :c:member:`PyConfig.use_environment`.
- If non-zero, configure C standard streams:
+ Default: ``1`` in Python config and ``0`` in isolated config.
- * On Windows, set the binary mode (``O_BINARY``) on stdin, stdout and
- stderr.
- * If :c:member:`~PyConfig.buffered_stdio` equals zero, disable buffering
- of stdin, stdout and stderr streams.
- * If :c:member:`~PyConfig.interactive` is non-zero, enable stream
- buffering on stdin and stdout (only stdout on Windows).
+ .. c:member:: int utf8_mode
- Default: ``1`` in Python config, ``0`` in isolated config.
+ If non-zero, enable the :ref:`Python UTF-8 Mode <utf8-mode>`.
- .. c:member:: int dev_mode
+ Set to ``0`` or ``1`` by the :option:`-X utf8 <-X>` command line option
+ and the :envvar:`PYTHONUTF8` environment variable.
- If non-zero, enable the :ref:`Python Development Mode <devmode>`.
+ Also set to ``1`` if the ``LC_CTYPE`` locale is ``C`` or ``POSIX``.
- Set to ``1`` by the :option:`-X dev <-X>` option and the
- :envvar:`PYTHONDEVMODE` environment variable.
+ Default: ``-1`` in Python config and ``0`` in isolated config.
- Default: ``-1`` in Python mode, ``0`` in isolated mode.
- .. c:member:: int dump_refs
+.. _c-preinit:
- Dump Python references?
+Preinitialize Python with PyPreConfig
+-------------------------------------
- If non-zero, dump all objects which are still alive at exit.
+The preinitialization of Python:
- Set to ``1`` by the :envvar:`PYTHONDUMPREFS` environment variable.
+* Set the Python memory allocators (:c:member:`PyPreConfig.allocator`)
+* Configure the LC_CTYPE locale (:term:`locale encoding`)
+* Set the :ref:`Python UTF-8 Mode <utf8-mode>`
+ (:c:member:`PyPreConfig.utf8_mode`)
- Needs a special build of Python with the ``Py_TRACE_REFS`` macro defined:
- see the :option:`configure --with-trace-refs option <--with-trace-refs>`.
+The current preconfiguration (``PyPreConfig`` type) is stored in
+``_PyRuntime.preconfig``.
- Default: ``0``.
+Functions to preinitialize Python:
- .. c:member:: wchar_t* exec_prefix
+.. c:function:: PyStatus Py_PreInitialize(const PyPreConfig *preconfig)
- The site-specific directory prefix where the platform-dependent Python
- files are installed: :data:`sys.exec_prefix`.
+ Preinitialize Python from *preconfig* preconfiguration.
- Default: ``NULL``.
+ *preconfig* must not be ``NULL``.
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+.. c:function:: PyStatus Py_PreInitializeFromBytesArgs(const PyPreConfig *preconfig, int argc, char * const *argv)
- See also :c:member:`PyConfig.base_exec_prefix`.
+ Preinitialize Python from *preconfig* preconfiguration.
- .. c:member:: wchar_t* executable
+ Parse *argv* command line arguments (bytes strings) if
+ :c:member:`~PyPreConfig.parse_argv` of *preconfig* is non-zero.
- The absolute path of the executable binary for the Python interpreter:
- :data:`sys.executable`.
+ *preconfig* must not be ``NULL``.
- Default: ``NULL``.
+.. c:function:: PyStatus Py_PreInitializeFromArgs(const PyPreConfig *preconfig, int argc, wchar_t * const * argv)
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+ Preinitialize Python from *preconfig* preconfiguration.
- See also :c:member:`PyConfig.base_executable`.
+ Parse *argv* command line arguments (wide strings) if
+ :c:member:`~PyPreConfig.parse_argv` of *preconfig* is non-zero.
- .. c:member:: int faulthandler
+ *preconfig* must not be ``NULL``.
- Enable faulthandler?
+The caller is responsible to handle exceptions (error or exit) using
+:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`.
- If non-zero, call :func:`faulthandler.enable` at startup.
+For :ref:`Python Configuration <init-python-config>`
+(:c:func:`PyPreConfig_InitPythonConfig`), if Python is initialized with
+command line arguments, the command line arguments must also be passed to
+preinitialize Python, since they have an effect on the pre-configuration
+like encodings. For example, the :option:`-X utf8 <-X>` command line option
+enables the :ref:`Python UTF-8 Mode <utf8-mode>`.
- Set to ``1`` by :option:`-X faulthandler <-X>` and the
- :envvar:`PYTHONFAULTHANDLER` environment variable.
+``PyMem_SetAllocator()`` can be called after :c:func:`Py_PreInitialize` and
+before :c:func:`Py_InitializeFromConfig` to install a custom memory allocator.
+It can be called before :c:func:`Py_PreInitialize` if
+:c:member:`PyPreConfig.allocator` is set to ``PYMEM_ALLOCATOR_NOT_SET``.
- Default: ``-1`` in Python mode, ``0`` in isolated mode.
+Python memory allocation functions like :c:func:`PyMem_RawMalloc` must not be
+used before the Python preinitialization, whereas calling directly ``malloc()``
+and ``free()`` is always safe. :c:func:`Py_DecodeLocale` must not be called
+before the Python preinitialization.
- .. c:member:: wchar_t* filesystem_encoding
+Example using the preinitialization to enable
+the :ref:`Python UTF-8 Mode <utf8-mode>`::
- :term:`Filesystem encoding <filesystem encoding and error handler>`:
- :func:`sys.getfilesystemencoding`.
+ PyStatus status;
+ PyPreConfig preconfig;
+ PyPreConfig_InitPythonConfig(&preconfig);
- On macOS, Android and VxWorks: use ``"utf-8"`` by default.
+ preconfig.utf8_mode = 1;
- On Windows: use ``"utf-8"`` by default, or ``"mbcs"`` if
- :c:member:`~PyPreConfig.legacy_windows_fs_encoding` of
- :c:type:`PyPreConfig` is non-zero.
+ status = Py_PreInitialize(&preconfig);
+ if (PyStatus_Exception(status)) {
+ Py_ExitStatusException(status);
+ }
- Default encoding on other platforms:
+ /* at this point, Python speaks UTF-8 */
- * ``"utf-8"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero.
- * ``"ascii"`` if Python detects that ``nl_langinfo(CODESET)`` announces
- the ASCII encoding, whereas the ``mbstowcs()`` function
- decodes from a different encoding (usually Latin1).
- * ``"utf-8"`` if ``nl_langinfo(CODESET)`` returns an empty string.
- * Otherwise, use the :term:`locale encoding`:
- ``nl_langinfo(CODESET)`` result.
+ Py_Initialize();
+ /* ... use Python API here ... */
+ Py_Finalize();
- At Python startup, the encoding name is normalized to the Python codec
- name. For example, ``"ANSI_X3.4-1968"`` is replaced with ``"ascii"``.
- See also the :c:member:`~PyConfig.filesystem_errors` member.
+PyConfig
+--------
- .. c:member:: wchar_t* filesystem_errors
+.. c:type:: PyConfig
- :term:`Filesystem error handler <filesystem encoding and error handler>`:
- :func:`sys.getfilesystemencodeerrors`.
+ Structure containing most parameters to configure Python.
- On Windows: use ``"surrogatepass"`` by default, or ``"replace"`` if
- :c:member:`~PyPreConfig.legacy_windows_fs_encoding` of
- :c:type:`PyPreConfig` is non-zero.
+ When done, the :c:func:`PyConfig_Clear` function must be used to release the
+ configuration memory.
- On other platforms: use ``"surrogateescape"`` by default.
+ .. c:namespace:: NULL
- Supported error handlers:
+ Structure methods:
- * ``"strict"``
- * ``"surrogateescape"``
- * ``"surrogatepass"`` (only supported with the UTF-8 encoding)
+ .. c:function:: void PyConfig_InitPythonConfig(PyConfig *config)
- See also the :c:member:`~PyConfig.filesystem_encoding` member.
+ Initialize configuration with the :ref:`Python Configuration
+ <init-python-config>`.
- .. c:member:: unsigned long hash_seed
- .. c:member:: int use_hash_seed
+ .. c:function:: void PyConfig_InitIsolatedConfig(PyConfig *config)
- Randomized hash function seed.
+ Initialize configuration with the :ref:`Isolated Configuration
+ <init-isolated-conf>`.
- If :c:member:`~PyConfig.use_hash_seed` is zero, a seed is chosen randomly
- at Python startup, and :c:member:`~PyConfig.hash_seed` is ignored.
+ .. c:function:: PyStatus PyConfig_SetString(PyConfig *config, wchar_t * const *config_str, const wchar_t *str)
- Set by the :envvar:`PYTHONHASHSEED` environment variable.
+ Copy the wide character string *str* into ``*config_str``.
- Default *use_hash_seed* value: ``-1`` in Python mode, ``0`` in isolated
- mode.
+ :ref:`Preinitialize Python <c-preinit>` if needed.
- .. c:member:: wchar_t* home
+ .. c:function:: PyStatus PyConfig_SetBytesString(PyConfig *config, wchar_t * const *config_str, const char *str)
- Set the default Python "home" directory, that is, the location of the
- standard Python libraries (see :envvar:`PYTHONHOME`).
+ Decode *str* using :c:func:`Py_DecodeLocale` and set the result into
+ ``*config_str``.
- Set by the :envvar:`PYTHONHOME` environment variable.
+ :ref:`Preinitialize Python <c-preinit>` if needed.
- Default: ``NULL``.
+ .. c:function:: PyStatus PyConfig_SetArgv(PyConfig *config, int argc, wchar_t * const *argv)
- Part of the :ref:`Python Path Configuration <init-path-config>` input.
+ Set command line arguments (:c:member:`~PyConfig.argv` member of
+ *config*) from the *argv* list of wide character strings.
- .. c:member:: int import_time
+ :ref:`Preinitialize Python <c-preinit>` if needed.
- If non-zero, profile import time.
+ .. c:function:: PyStatus PyConfig_SetBytesArgv(PyConfig *config, int argc, char * const *argv)
- Set the ``1`` by the :option:`-X importtime <-X>` option and the
- :envvar:`PYTHONPROFILEIMPORTTIME` environment variable.
+ Set command line arguments (:c:member:`~PyConfig.argv` member of
+ *config*) from the *argv* list of bytes strings. Decode bytes using
+ :c:func:`Py_DecodeLocale`.
- Default: ``0``.
+ :ref:`Preinitialize Python <c-preinit>` if needed.
- .. c:member:: int inspect
+ .. c:function:: PyStatus PyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list, Py_ssize_t length, wchar_t **items)
- Enter interactive mode after executing a script or a command.
+ Set the list of wide strings *list* to *length* and *items*.
- If greater than ``0``, enable inspect: when a script is passed as first
- argument or the -c option is used, enter interactive mode after executing
- the script or the command, even when :data:`sys.stdin` does not appear to
- be a terminal.
+ :ref:`Preinitialize Python <c-preinit>` if needed.
- Incremented by the :option:`-i` command line option. Set to ``1`` if the
- :envvar:`PYTHONINSPECT` environment variable is non-empty.
+ .. c:function:: PyStatus PyConfig_Read(PyConfig *config)
- Default: ``0``.
+ Read all Python configuration.
- .. c:member:: int install_signal_handlers
+ Fields which are already initialized are left unchanged.
- Install Python signal handlers?
+ Fields for :ref:`path configuration <init-path-config>` are no longer
+ calculated or modified when calling this function, as of Python 3.11.
- Default: ``1`` in Python mode, ``0`` in isolated mode.
-
- .. c:member:: int interactive
-
- If greater than ``0``, enable the interactive mode (REPL).
-
- Incremented by the :option:`-i` command line option.
+ The :c:func:`PyConfig_Read` function only parses
+ :c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv`
+ is set to ``2`` after arguments are parsed. Since Python arguments are
+ stripped from :c:member:`PyConfig.argv`, parsing arguments twice would
+ parse the application options as Python options.
- Default: ``0``.
+ :ref:`Preinitialize Python <c-preinit>` if needed.
- .. c:member:: int int_max_str_digits
+ .. versionchanged:: 3.10
+ The :c:member:`PyConfig.argv` arguments are now only parsed once,
+ :c:member:`PyConfig.parse_argv` is set to ``2`` after arguments are
+ parsed, and arguments are only parsed if
+ :c:member:`PyConfig.parse_argv` equals ``1``.
- Configures the :ref:`integer string conversion length limitation
- <int_max_str_digits>`. An initial value of ``-1`` means the value will
- be taken from the command line or environment or otherwise default to
- 4300 (:data:`sys.int_info.default_max_str_digits`). A value of ``0``
- disables the limitation. Values greater than zero but less than 640
- (:data:`sys.int_info.str_digits_check_threshold`) are unsupported and
- will produce an error.
+ .. versionchanged:: 3.11
+ :c:func:`PyConfig_Read` no longer calculates all paths, and so fields
+ listed under :ref:`Python Path Configuration <init-path-config>` may
+ no longer be updated until :c:func:`Py_InitializeFromConfig` is
+ called.
- Configured by the :option:`-X int_max_str_digits <-X>` command line
- flag or the :envvar:`PYTHONINTMAXSTRDIGITS` environment variable.
+ .. c:function:: void PyConfig_Clear(PyConfig *config)
- Default: ``-1`` in Python mode. 4300
- (:data:`sys.int_info.default_max_str_digits`) in isolated mode.
+ Release configuration memory.
- .. versionadded:: 3.12
+ Most ``PyConfig`` methods :ref:`preinitialize Python <c-preinit>` if needed.
+ In that case, the Python preinitialization configuration
+ (:c:type:`PyPreConfig`) in based on the :c:type:`PyConfig`. If configuration
+ fields which are in common with :c:type:`PyPreConfig` are tuned, they must
+ be set before calling a :c:type:`PyConfig` method:
- .. c:member:: int cpu_count
+ * :c:member:`PyConfig.dev_mode`
+ * :c:member:`PyConfig.isolated`
+ * :c:member:`PyConfig.parse_argv`
+ * :c:member:`PyConfig.use_environment`
- If the value of :c:member:`~PyConfig.cpu_count` is not ``-1`` then it will
- override the return values of :func:`os.cpu_count`,
- :func:`os.process_cpu_count`, and :func:`multiprocessing.cpu_count`.
+ Moreover, if :c:func:`PyConfig_SetArgv` or :c:func:`PyConfig_SetBytesArgv`
+ is used, this method must be called before other methods, since the
+ preinitialization configuration depends on command line arguments (if
+ :c:member:`~PyConfig.parse_argv` is non-zero).
- Configured by the :samp:`-X cpu_count={n|default}` command line
- flag or the :envvar:`PYTHON_CPU_COUNT` environment variable.
+ The caller of these methods is responsible to handle exceptions (error or
+ exit) using ``PyStatus_Exception()`` and ``Py_ExitStatusException()``.
- Default: ``-1``.
+ .. c:namespace:: PyConfig
- .. versionadded:: 3.13
+ Structure fields:
- .. c:member:: int isolated
+ .. c:member:: PyWideStringList argv
- If greater than ``0``, enable isolated mode:
+ .. index::
+ single: main()
+ single: argv (in module sys)
- * Set :c:member:`~PyConfig.safe_path` to ``1``:
- don't prepend a potentially unsafe path to :data:`sys.path` at Python
- startup, such as the current directory, the script's directory or an
- empty string.
- * Set :c:member:`~PyConfig.use_environment` to ``0``: ignore ``PYTHON``
- environment variables.
- * Set :c:member:`~PyConfig.user_site_directory` to ``0``: don't add the user
- site directory to :data:`sys.path`.
- * Python REPL doesn't import :mod:`readline` nor enable default readline
- configuration on interactive prompts.
+ 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 to ``1`` by the :option:`-I` command line option.
+ Set :c:member:`~PyConfig.parse_argv` to ``1`` to parse
+ :c:member:`~PyConfig.argv` the same way the regular Python parses Python
+ command line arguments and then to strip Python arguments from
+ :c:member:`~PyConfig.argv`.
- Default: ``0`` in Python mode, ``1`` in isolated mode.
+ If :c:member:`~PyConfig.argv` is empty, an empty string is added to
+ ensure that :data:`sys.argv` always exists and is never empty.
- See also the :ref:`Isolated Configuration <init-isolated-conf>` and
- :c:member:`PyPreConfig.isolated`.
+ Default: ``NULL``.
- .. c:member:: int legacy_windows_stdio
+ See also the :c:member:`~PyConfig.orig_argv` member.
- If non-zero, use :class:`io.FileIO` instead of
- :class:`!io._WindowsConsoleIO` for :data:`sys.stdin`, :data:`sys.stdout`
- and :data:`sys.stderr`.
+ .. c:member:: int safe_path
- Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSSTDIO` environment
- variable is set to a non-empty string.
+ If equals to zero, ``Py_RunMain()`` prepends a potentially unsafe path to
+ :data:`sys.path` at startup:
- Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
- Windows specific code.
+ * If :c:member:`argv[0] <PyConfig.argv>` is equal to ``L"-m"``
+ (``python -m module``), prepend the current working directory.
+ * If running a script (``python script.py``), prepend the script's
+ directory. If it's a symbolic link, resolve symbolic links.
+ * Otherwise (``python -c code`` and ``python``), prepend an empty string,
+ which means the current working directory.
- Default: ``0``.
+ Set to ``1`` by the :option:`-P` command line option and the
+ :envvar:`PYTHONSAFEPATH` environment variable.
- See also the :pep:`528` (Change Windows console encoding to UTF-8).
+ Default: ``0`` in Python config, ``1`` in isolated config.
- .. c:member:: int malloc_stats
+ .. versionadded:: 3.11
- If non-zero, dump statistics on :ref:`Python pymalloc memory allocator
- <pymalloc>` at exit.
+ .. c:member:: wchar_t* base_exec_prefix
- Set to ``1`` by the :envvar:`PYTHONMALLOCSTATS` environment variable.
+ :data:`sys.base_exec_prefix`.
- The option is ignored if Python is :option:`configured using
- the --without-pymalloc option <--without-pymalloc>`.
+ Default: ``NULL``.
- Default: ``0``.
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
- .. c:member:: wchar_t* platlibdir
+ See also :c:member:`PyConfig.exec_prefix`.
- Platform library directory name: :data:`sys.platlibdir`.
+ .. c:member:: wchar_t* base_executable
- Set by the :envvar:`PYTHONPLATLIBDIR` environment variable.
+ Python base executable: :data:`sys._base_executable`.
- Default: value of the ``PLATLIBDIR`` macro which is set by the
- :option:`configure --with-platlibdir option <--with-platlibdir>`
- (default: ``"lib"``, or ``"DLLs"`` on Windows).
+ Set by the :envvar:`__PYVENV_LAUNCHER__` environment variable.
- Part of the :ref:`Python Path Configuration <init-path-config>` input.
+ Set from :c:member:`PyConfig.executable` if ``NULL``.
- .. versionadded:: 3.9
+ Default: ``NULL``.
- .. versionchanged:: 3.11
- This macro is now used on Windows to locate the standard
- library extension modules, typically under ``DLLs``. However,
- for compatibility, note that this value is ignored for any
- non-standard layouts, including in-tree builds and virtual
- environments.
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
- .. c:member:: wchar_t* pythonpath_env
+ See also :c:member:`PyConfig.executable`.
- Module search paths (:data:`sys.path`) as a string separated by ``DELIM``
- (:data:`os.pathsep`).
+ .. c:member:: wchar_t* base_prefix
- Set by the :envvar:`PYTHONPATH` environment variable.
+ :data:`sys.base_prefix`.
Default: ``NULL``.
- Part of the :ref:`Python Path Configuration <init-path-config>` input.
-
- .. c:member:: PyWideStringList module_search_paths
- .. c:member:: int module_search_paths_set
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
- Module search paths: :data:`sys.path`.
+ See also :c:member:`PyConfig.prefix`.
- If :c:member:`~PyConfig.module_search_paths_set` is equal to ``0``,
- :c:func:`Py_InitializeFromConfig` will replace
- :c:member:`~PyConfig.module_search_paths` and sets
- :c:member:`~PyConfig.module_search_paths_set` to ``1``.
+ .. c:member:: int buffered_stdio
- Default: empty list (``module_search_paths``) and ``0``
- (``module_search_paths_set``).
+ If equals to ``0`` and :c:member:`~PyConfig.configure_c_stdio` is non-zero,
+ disable buffering on the C streams stdout and stderr.
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+ Set to ``0`` by the :option:`-u` command line option and the
+ :envvar:`PYTHONUNBUFFERED` environment variable.
- .. c:member:: int optimization_level
+ stdin is always opened in buffered mode.
- Compilation optimization level:
+ Default: ``1``.
- * ``0``: Peephole optimizer, set ``__debug__`` to ``True``.
- * ``1``: Level 0, remove assertions, set ``__debug__`` to ``False``.
- * ``2``: Level 1, strip docstrings.
+ .. c:member:: int bytes_warning
- Incremented by the :option:`-O` command line option. Set to the
- :envvar:`PYTHONOPTIMIZE` environment variable value.
+ If equals to ``1``, issue a warning when comparing :class:`bytes` or
+ :class:`bytearray` with :class:`str`, or comparing :class:`bytes` with
+ :class:`int`.
- Default: ``0``.
+ If equal or greater to ``2``, raise a :exc:`BytesWarning` exception in these
+ cases.
- .. c:member:: PyWideStringList orig_argv
+ Incremented by the :option:`-b` command line option.
- The list of the original command line arguments passed to the Python
- executable: :data:`sys.orig_argv`.
+ Default: ``0``.
- If :c:member:`~PyConfig.orig_argv` list is empty and
- :c:member:`~PyConfig.argv` is not a list only containing an empty
- string, :c:func:`PyConfig_Read` copies :c:member:`~PyConfig.argv` into
- :c:member:`~PyConfig.orig_argv` before modifying
- :c:member:`~PyConfig.argv` (if :c:member:`~PyConfig.parse_argv` is
- non-zero).
+ .. c:member:: int warn_default_encoding
- See also the :c:member:`~PyConfig.argv` member and the
- :c:func:`Py_GetArgcArgv` function.
+ If non-zero, emit a :exc:`EncodingWarning` warning when :class:`io.TextIOWrapper`
+ uses its default encoding. See :ref:`io-encoding-warning` for details.
- Default: empty list.
+ Default: ``0``.
.. versionadded:: 3.10
- .. c:member:: int parse_argv
+ .. c:member:: int code_debug_ranges
- Parse command line arguments?
+ If equals to ``0``, disables the inclusion of the end line and column
+ mappings in code objects. Also disables traceback printing carets to
+ specific error locations.
- If equals to ``1``, parse :c:member:`~PyConfig.argv` the same way the regular
- Python parses :ref:`command line arguments <using-on-cmdline>`, and strip
- Python arguments from :c:member:`~PyConfig.argv`.
+ Set to ``0`` by the :envvar:`PYTHONNODEBUGRANGES` environment variable
+ and by the :option:`-X no_debug_ranges <-X>` command line option.
- The :c:func:`PyConfig_Read` function only parses
- :c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv`
- is set to ``2`` after arguments are parsed. Since Python arguments are
- stripped from :c:member:`PyConfig.argv`, parsing arguments twice would
- parse the application options as Python options.
+ Default: ``1``.
- Default: ``1`` in Python mode, ``0`` in isolated mode.
+ .. versionadded:: 3.11
- .. versionchanged:: 3.10
- The :c:member:`PyConfig.argv` arguments are now only parsed if
- :c:member:`PyConfig.parse_argv` equals to ``1``.
+ .. c:member:: wchar_t* check_hash_pycs_mode
- .. c:member:: int parser_debug
+ Control the validation behavior of hash-based ``.pyc`` files:
+ value of the :option:`--check-hash-based-pycs` command line option.
- Parser debug mode. If greater than ``0``, turn on parser debugging output (for expert only, depending
- on compilation options).
+ Valid values:
- Incremented by the :option:`-d` command line option. Set to the
- :envvar:`PYTHONDEBUG` environment variable value.
+ - ``L"always"``: Hash the source file for invalidation regardless of
+ value of the 'check_source' flag.
+ - ``L"never"``: Assume that hash-based pycs always are valid.
+ - ``L"default"``: The 'check_source' flag in hash-based pycs
+ determines invalidation.
- Needs a :ref:`debug build of Python <debug-build>` (the ``Py_DEBUG`` macro
- must be defined).
+ Default: ``L"default"``.
- Default: ``0``.
+ See also :pep:`552` "Deterministic pycs".
- .. c:member:: int pathconfig_warnings
-
- If non-zero, calculation of path configuration is allowed to log
- warnings into ``stderr``. If equals to ``0``, suppress these warnings.
-
- Default: ``1`` in Python mode, ``0`` in isolated mode.
-
- Part of the :ref:`Python Path Configuration <init-path-config>` input.
+ .. c:member:: int configure_c_stdio
- .. versionchanged:: 3.11
- Now also applies on Windows.
+ If non-zero, configure C standard streams:
- .. c:member:: wchar_t* prefix
+ * On Windows, set the binary mode (``O_BINARY``) on stdin, stdout and
+ stderr.
+ * If :c:member:`~PyConfig.buffered_stdio` equals zero, disable buffering
+ of stdin, stdout and stderr streams.
+ * If :c:member:`~PyConfig.interactive` is non-zero, enable stream
+ buffering on stdin and stdout (only stdout on Windows).
- The site-specific directory prefix where the platform independent Python
- files are installed: :data:`sys.prefix`.
+ Default: ``1`` in Python config, ``0`` in isolated config.
- Default: ``NULL``.
+ .. c:member:: int dev_mode
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+ If non-zero, enable the :ref:`Python Development Mode <devmode>`.
- See also :c:member:`PyConfig.base_prefix`.
+ Set to ``1`` by the :option:`-X dev <-X>` option and the
+ :envvar:`PYTHONDEVMODE` environment variable.
- .. c:member:: wchar_t* program_name
+ Default: ``-1`` in Python mode, ``0`` in isolated mode.
- Program name used to initialize :c:member:`~PyConfig.executable` and in
- early error messages during Python initialization.
+ .. c:member:: int dump_refs
- * 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.
- * Use ``argv[0]`` of :c:member:`~PyConfig.argv` if available and
- non-empty.
- * Otherwise, use ``L"python"`` on Windows, or ``L"python3"`` on other
- platforms.
+ Dump Python references?
- Default: ``NULL``.
+ If non-zero, dump all objects which are still alive at exit.
- Part of the :ref:`Python Path Configuration <init-path-config>` input.
+ Set to ``1`` by the :envvar:`PYTHONDUMPREFS` environment variable.
- .. c:member:: wchar_t* pycache_prefix
+ Needs a special build of Python with the ``Py_TRACE_REFS`` macro defined:
+ see the :option:`configure --with-trace-refs option <--with-trace-refs>`.
- Directory where cached ``.pyc`` files are written:
- :data:`sys.pycache_prefix`.
+ Default: ``0``.
- Set by the :option:`-X pycache_prefix=PATH <-X>` command line option and
- the :envvar:`PYTHONPYCACHEPREFIX` environment variable.
- The command-line option takes precedence.
+ .. c:member:: wchar_t* exec_prefix
- If ``NULL``, :data:`sys.pycache_prefix` is set to ``None``.
+ The site-specific directory prefix where the platform-dependent Python
+ files are installed: :data:`sys.exec_prefix`.
Default: ``NULL``.
- .. c:member:: int quiet
-
- Quiet mode. If greater than ``0``, don't display the copyright and version at
- Python startup in interactive mode.
-
- Incremented by the :option:`-q` command line option.
-
- Default: ``0``.
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
- .. c:member:: wchar_t* run_command
+ See also :c:member:`PyConfig.base_exec_prefix`.
- Value of the :option:`-c` command line option.
+ .. c:member:: wchar_t* executable
- Used by :c:func:`Py_RunMain`.
+ The absolute path of the executable binary for the Python interpreter:
+ :data:`sys.executable`.
Default: ``NULL``.
- .. c:member:: wchar_t* run_filename
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
- Filename passed on the command line: trailing command line argument
- without :option:`-c` or :option:`-m`. It is used by the
- :c:func:`Py_RunMain` function.
+ See also :c:member:`PyConfig.base_executable`.
- For example, it is set to ``script.py`` by the ``python3 script.py arg``
- command line.
+ .. c:member:: int faulthandler
- See also the :c:member:`PyConfig.skip_source_first_line` option.
+ Enable faulthandler?
- Default: ``NULL``.
+ If non-zero, call :func:`faulthandler.enable` at startup.
- .. c:member:: wchar_t* run_module
+ Set to ``1`` by :option:`-X faulthandler <-X>` and the
+ :envvar:`PYTHONFAULTHANDLER` environment variable.
- Value of the :option:`-m` command line option.
+ Default: ``-1`` in Python mode, ``0`` in isolated mode.
- Used by :c:func:`Py_RunMain`.
+ .. c:member:: wchar_t* filesystem_encoding
- Default: ``NULL``.
+ :term:`Filesystem encoding <filesystem encoding and error handler>`:
+ :func:`sys.getfilesystemencoding`.
- .. c:member:: wchar_t* run_presite
+ On macOS, Android and VxWorks: use ``"utf-8"`` by default.
- ``package.module`` path to module that should be imported before
- ``site.py`` is run.
+ On Windows: use ``"utf-8"`` by default, or ``"mbcs"`` if
+ :c:member:`~PyPreConfig.legacy_windows_fs_encoding` of
+ :c:type:`PyPreConfig` is non-zero.
- Set by the :option:`-X presite=package.module <-X>` command-line
- option and the :envvar:`PYTHON_PRESITE` environment variable.
- The command-line option takes precedence.
+ Default encoding on other platforms:
- Needs a :ref:`debug build of Python <debug-build>` (the ``Py_DEBUG`` macro
- must be defined).
+ * ``"utf-8"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero.
+ * ``"ascii"`` if Python detects that ``nl_langinfo(CODESET)`` announces
+ the ASCII encoding, whereas the ``mbstowcs()`` function
+ decodes from a different encoding (usually Latin1).
+ * ``"utf-8"`` if ``nl_langinfo(CODESET)`` returns an empty string.
+ * Otherwise, use the :term:`locale encoding`:
+ ``nl_langinfo(CODESET)`` result.
- Default: ``NULL``.
+ At Python startup, the encoding name is normalized to the Python codec
+ name. For example, ``"ANSI_X3.4-1968"`` is replaced with ``"ascii"``.
- .. c:member:: int show_ref_count
+ See also the :c:member:`~PyConfig.filesystem_errors` member.
- Show total reference count at exit (excluding :term:`immortal` objects)?
+ .. c:member:: wchar_t* filesystem_errors
- Set to ``1`` by :option:`-X showrefcount <-X>` command line option.
+ :term:`Filesystem error handler <filesystem encoding and error handler>`:
+ :func:`sys.getfilesystemencodeerrors`.
- Needs a :ref:`debug build of Python <debug-build>` (the ``Py_REF_DEBUG``
- macro must be defined).
+ On Windows: use ``"surrogatepass"`` by default, or ``"replace"`` if
+ :c:member:`~PyPreConfig.legacy_windows_fs_encoding` of
+ :c:type:`PyPreConfig` is non-zero.
- Default: ``0``.
+ On other platforms: use ``"surrogateescape"`` by default.
- .. c:member:: int site_import
+ Supported error handlers:
- Import the :mod:`site` module at startup?
+ * ``"strict"``
+ * ``"surrogateescape"``
+ * ``"surrogatepass"`` (only supported with the UTF-8 encoding)
- If equal to zero, disable the import of the module site and the
- site-dependent manipulations of :data:`sys.path` that it entails.
+ See also the :c:member:`~PyConfig.filesystem_encoding` member.
- Also disable these manipulations if the :mod:`site` module is explicitly
- imported later (call :func:`site.main` if you want them to be triggered).
+ .. c:member:: unsigned long hash_seed
+ .. c:member:: int use_hash_seed
- Set to ``0`` by the :option:`-S` command line option.
+ Randomized hash function seed.
- :data:`sys.flags.no_site <sys.flags>` is set to the inverted value of
- :c:member:`~PyConfig.site_import`.
+ If :c:member:`~PyConfig.use_hash_seed` is zero, a seed is chosen randomly
+ at Python startup, and :c:member:`~PyConfig.hash_seed` is ignored.
- Default: ``1``.
+ Set by the :envvar:`PYTHONHASHSEED` environment variable.
- .. c:member:: int skip_source_first_line
+ Default *use_hash_seed* value: ``-1`` in Python mode, ``0`` in isolated
+ mode.
- If non-zero, skip the first line of the :c:member:`PyConfig.run_filename`
- source.
+ .. c:member:: wchar_t* home
- It allows the usage of non-Unix forms of ``#!cmd``. This is intended for
- a DOS specific hack only.
+ Set the default Python "home" directory, that is, the location of the
+ standard Python libraries (see :envvar:`PYTHONHOME`).
- Set to ``1`` by the :option:`-x` command line option.
+ Set by the :envvar:`PYTHONHOME` environment variable.
- Default: ``0``.
+ Default: ``NULL``.
- .. c:member:: wchar_t* stdio_encoding
- .. c:member:: wchar_t* stdio_errors
+ Part of the :ref:`Python Path Configuration <init-path-config>` input.
- Encoding and encoding errors of :data:`sys.stdin`, :data:`sys.stdout` and
- :data:`sys.stderr` (but :data:`sys.stderr` always uses
- ``"backslashreplace"`` error handler).
+ .. c:member:: int import_time
- Use the :envvar:`PYTHONIOENCODING` environment variable if it is
- non-empty.
+ If non-zero, profile import time.
- Default encoding:
+ Set the ``1`` by the :option:`-X importtime <-X>` option and the
+ :envvar:`PYTHONPROFILEIMPORTTIME` environment variable.
- * ``"UTF-8"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero.
- * Otherwise, use the :term:`locale encoding`.
+ Default: ``0``.
- Default error handler:
+ .. c:member:: int inspect
- * On Windows: use ``"surrogateescape"``.
- * ``"surrogateescape"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero,
- or if the LC_CTYPE locale is "C" or "POSIX".
- * ``"strict"`` otherwise.
+ Enter interactive mode after executing a script or a command.
- See also :c:member:`PyConfig.legacy_windows_stdio`.
+ If greater than ``0``, enable inspect: when a script is passed as first
+ argument or the -c option is used, enter interactive mode after executing
+ the script or the command, even when :data:`sys.stdin` does not appear to
+ be a terminal.
- .. c:member:: int tracemalloc
+ Incremented by the :option:`-i` command line option. Set to ``1`` if the
+ :envvar:`PYTHONINSPECT` environment variable is non-empty.
- Enable tracemalloc?
+ Default: ``0``.
- If non-zero, call :func:`tracemalloc.start` at startup.
+ .. c:member:: int install_signal_handlers
- Set by :option:`-X tracemalloc=N <-X>` command line option and by the
- :envvar:`PYTHONTRACEMALLOC` environment variable.
+ Install Python signal handlers?
- Default: ``-1`` in Python mode, ``0`` in isolated mode.
+ Default: ``1`` in Python mode, ``0`` in isolated mode.
- .. c:member:: int perf_profiling
+ .. c:member:: int interactive
- Enable the Linux ``perf`` profiler support?
+ If greater than ``0``, enable the interactive mode (REPL).
- If equals to ``1``, enable support for the Linux ``perf`` profiler.
+ Incremented by the :option:`-i` command line option.
- If equals to ``2``, enable support for the Linux ``perf`` profiler with
- DWARF JIT support.
+ Default: ``0``.
- Set to ``1`` by :option:`-X perf <-X>` command-line option and the
- :envvar:`PYTHONPERFSUPPORT` environment variable.
+ .. c:member:: int int_max_str_digits
- Set to ``2`` by the :option:`-X perf_jit <-X>` command-line option and
- the :envvar:`PYTHON_PERF_JIT_SUPPORT` environment variable.
+ Configures the :ref:`integer string conversion length limitation
+ <int_max_str_digits>`. An initial value of ``-1`` means the value will
+ be taken from the command line or environment or otherwise default to
+ 4300 (:data:`sys.int_info.default_max_str_digits`). A value of ``0``
+ disables the limitation. Values greater than zero but less than 640
+ (:data:`sys.int_info.str_digits_check_threshold`) are unsupported and
+ will produce an error.
- Default: ``-1``.
+ Configured by the :option:`-X int_max_str_digits <-X>` command line
+ flag or the :envvar:`PYTHONINTMAXSTRDIGITS` environment variable.
- .. seealso::
- See :ref:`perf_profiling` for more information.
+ Default: ``-1`` in Python mode. 4300
+ (:data:`sys.int_info.default_max_str_digits`) in isolated mode.
.. versionadded:: 3.12
- .. c:member:: int use_environment
+ .. c:member:: int cpu_count
- Use :ref:`environment variables <using-on-envvars>`?
+ If the value of :c:member:`~PyConfig.cpu_count` is not ``-1`` then it will
+ override the return values of :func:`os.cpu_count`,
+ :func:`os.process_cpu_count`, and :func:`multiprocessing.cpu_count`.
- If equals to zero, ignore the :ref:`environment variables
- <using-on-envvars>`.
+ Configured by the :samp:`-X cpu_count={n|default}` command line
+ flag or the :envvar:`PYTHON_CPU_COUNT` environment variable.
- Set to ``0`` by the :option:`-E` environment variable.
+ Default: ``-1``.
- Default: ``1`` in Python config and ``0`` in isolated config.
+ .. versionadded:: 3.13
- .. c:member:: int use_system_logger
+ .. c:member:: int isolated
- If non-zero, ``stdout`` and ``stderr`` will be redirected to the system
- log.
+ If greater than ``0``, enable isolated mode:
- Only available on macOS 10.12 and later, and on iOS.
+ * Set :c:member:`~PyConfig.safe_path` to ``1``:
+ don't prepend a potentially unsafe path to :data:`sys.path` at Python
+ startup, such as the current directory, the script's directory or an
+ empty string.
+ * Set :c:member:`~PyConfig.use_environment` to ``0``: ignore ``PYTHON``
+ environment variables.
+ * Set :c:member:`~PyConfig.user_site_directory` to ``0``: don't add the user
+ site directory to :data:`sys.path`.
+ * Python REPL doesn't import :mod:`readline` nor enable default readline
+ configuration on interactive prompts.
- Default: ``0`` (don't use system log).
+ Set to ``1`` by the :option:`-I` command line option.
- .. versionadded:: 3.13.2
+ Default: ``0`` in Python mode, ``1`` in isolated mode.
- .. c:member:: int user_site_directory
+ See also the :ref:`Isolated Configuration <init-isolated-conf>` and
+ :c:member:`PyPreConfig.isolated`.
- If non-zero, add the user site directory to :data:`sys.path`.
+ .. c:member:: int legacy_windows_stdio
- Set to ``0`` by the :option:`-s` and :option:`-I` command line options.
+ If non-zero, use :class:`io.FileIO` instead of
+ :class:`!io._WindowsConsoleIO` for :data:`sys.stdin`, :data:`sys.stdout`
+ and :data:`sys.stderr`.
- Set to ``0`` by the :envvar:`PYTHONNOUSERSITE` environment variable.
+ Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSSTDIO` environment
+ variable is set to a non-empty string.
- Default: ``1`` in Python mode, ``0`` in isolated mode.
+ Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
+ Windows specific code.
- .. c:member:: int verbose
+ Default: ``0``.
- Verbose mode. If greater than ``0``, print a message each time a module is
- imported, showing the place (filename or built-in module) from which
- it is loaded.
+ See also the :pep:`528` (Change Windows console encoding to UTF-8).
- If greater than or equal to ``2``, print a message for each file that is
- checked for when searching for a module. Also provides information on
- module cleanup at exit.
+ .. c:member:: int malloc_stats
- Incremented by the :option:`-v` command line option.
+ If non-zero, dump statistics on :ref:`Python pymalloc memory allocator
+ <pymalloc>` at exit.
- Set by the :envvar:`PYTHONVERBOSE` environment variable value.
+ Set to ``1`` by the :envvar:`PYTHONMALLOCSTATS` environment variable.
+
+ The option is ignored if Python is :option:`configured using
+ the --without-pymalloc option <--without-pymalloc>`.
Default: ``0``.
- .. c:member:: PyWideStringList warnoptions
+ .. c:member:: wchar_t* platlibdir
- Options of the :mod:`warnings` module to build warnings filters, lowest
- to highest priority: :data:`sys.warnoptions`.
+ Platform library directory name: :data:`sys.platlibdir`.
- The :mod:`warnings` module adds :data:`sys.warnoptions` in the reverse
- order: the last :c:member:`PyConfig.warnoptions` item becomes the first
- item of :data:`warnings.filters` which is checked first (highest
- priority).
+ Set by the :envvar:`PYTHONPLATLIBDIR` environment variable.
- The :option:`-W` command line options adds its value to
- :c:member:`~PyConfig.warnoptions`, it can be used multiple times.
+ Default: value of the ``PLATLIBDIR`` macro which is set by the
+ :option:`configure --with-platlibdir option <--with-platlibdir>`
+ (default: ``"lib"``, or ``"DLLs"`` on Windows).
- The :envvar:`PYTHONWARNINGS` environment variable can also be used to add
- warning options. Multiple options can be specified, separated by commas
- (``,``).
+ Part of the :ref:`Python Path Configuration <init-path-config>` input.
- Default: empty list.
+ .. versionadded:: 3.9
- .. c:member:: int write_bytecode
+ .. versionchanged:: 3.11
+ This macro is now used on Windows to locate the standard
+ library extension modules, typically under ``DLLs``. However,
+ for compatibility, note that this value is ignored for any
+ non-standard layouts, including in-tree builds and virtual
+ environments.
- If equal to ``0``, Python won't try to write ``.pyc`` files on the import of
- source modules.
+ .. c:member:: wchar_t* pythonpath_env
- Set to ``0`` by the :option:`-B` command line option and the
- :envvar:`PYTHONDONTWRITEBYTECODE` environment variable.
+ Module search paths (:data:`sys.path`) as a string separated by ``DELIM``
+ (:data:`os.pathsep`).
- :data:`sys.dont_write_bytecode` is initialized to the inverted value of
- :c:member:`~PyConfig.write_bytecode`.
+ Set by the :envvar:`PYTHONPATH` environment variable.
- Default: ``1``.
+ Default: ``NULL``.
- .. c:member:: PyWideStringList xoptions
+ Part of the :ref:`Python Path Configuration <init-path-config>` input.
- Values of the :option:`-X` command line options: :data:`sys._xoptions`.
+ .. c:member:: PyWideStringList module_search_paths
+ .. c:member:: int module_search_paths_set
- Default: empty list.
+ Module search paths: :data:`sys.path`.
-If :c:member:`~PyConfig.parse_argv` is non-zero, :c:member:`~PyConfig.argv`
-arguments are parsed the same way the regular Python parses :ref:`command line
-arguments <using-on-cmdline>`, and Python arguments are stripped from
-:c:member:`~PyConfig.argv`.
+ If :c:member:`~PyConfig.module_search_paths_set` is equal to ``0``,
+ :c:func:`Py_InitializeFromConfig` will replace
+ :c:member:`~PyConfig.module_search_paths` and sets
+ :c:member:`~PyConfig.module_search_paths_set` to ``1``.
-The :c:member:`~PyConfig.xoptions` options are parsed to set other options: see
-the :option:`-X` command line option.
+ Default: empty list (``module_search_paths``) and ``0``
+ (``module_search_paths_set``).
-.. versionchanged:: 3.9
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
- The ``show_alloc_count`` field has been removed.
+ .. c:member:: int optimization_level
+ Compilation optimization level:
-.. _init-from-config:
+ * ``0``: Peephole optimizer, set ``__debug__`` to ``True``.
+ * ``1``: Level 0, remove assertions, set ``__debug__`` to ``False``.
+ * ``2``: Level 1, strip docstrings.
-Initialization with PyConfig
-----------------------------
+ Incremented by the :option:`-O` command line option. Set to the
+ :envvar:`PYTHONOPTIMIZE` environment variable value.
-Initializing the interpreter from a populated configuration struct is handled
-by calling :c:func:`Py_InitializeFromConfig`.
+ Default: ``0``.
-The caller is responsible to handle exceptions (error or exit) using
-:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`.
+ .. c:member:: PyWideStringList orig_argv
-If :c:func:`PyImport_FrozenModules`, :c:func:`PyImport_AppendInittab` or
-:c:func:`PyImport_ExtendInittab` are used, they must be set or called after
-Python preinitialization and before the Python initialization. If Python is
-initialized multiple times, :c:func:`PyImport_AppendInittab` or
-:c:func:`PyImport_ExtendInittab` must be called before each Python
-initialization.
+ The list of the original command line arguments passed to the Python
+ executable: :data:`sys.orig_argv`.
-The current configuration (``PyConfig`` type) is stored in
-``PyInterpreterState.config``.
+ If :c:member:`~PyConfig.orig_argv` list is empty and
+ :c:member:`~PyConfig.argv` is not a list only containing an empty
+ string, :c:func:`PyConfig_Read` copies :c:member:`~PyConfig.argv` into
+ :c:member:`~PyConfig.orig_argv` before modifying
+ :c:member:`~PyConfig.argv` (if :c:member:`~PyConfig.parse_argv` is
+ non-zero).
-Example setting the program name::
+ See also the :c:member:`~PyConfig.argv` member and the
+ :c:func:`Py_GetArgcArgv` function.
- void init_python(void)
- {
- PyStatus status;
+ Default: empty list.
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
+ .. versionadded:: 3.10
- /* Set the program name. Implicitly preinitialize Python. */
- status = PyConfig_SetString(&config, &config.program_name,
- L"/path/to/my_program");
- if (PyStatus_Exception(status)) {
- goto exception;
- }
+ .. c:member:: int parse_argv
- status = Py_InitializeFromConfig(&config);
- if (PyStatus_Exception(status)) {
- goto exception;
- }
- PyConfig_Clear(&config);
- return;
+ Parse command line arguments?
- exception:
- PyConfig_Clear(&config);
- Py_ExitStatusException(status);
- }
+ If equals to ``1``, parse :c:member:`~PyConfig.argv` the same way the regular
+ Python parses :ref:`command line arguments <using-on-cmdline>`, and strip
+ Python arguments from :c:member:`~PyConfig.argv`.
-More complete example modifying the default configuration, read the
-configuration, and then override some parameters. Note that since
-3.11, many parameters are not calculated until initialization, and
-so values cannot be read from the configuration structure. Any values
-set before initialize is called will be left unchanged by
-initialization::
+ The :c:func:`PyConfig_Read` function only parses
+ :c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv`
+ is set to ``2`` after arguments are parsed. Since Python arguments are
+ stripped from :c:member:`PyConfig.argv`, parsing arguments twice would
+ parse the application options as Python options.
- PyStatus init_python(const char *program_name)
- {
- PyStatus status;
+ Default: ``1`` in Python mode, ``0`` in isolated mode.
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
+ .. versionchanged:: 3.10
+ The :c:member:`PyConfig.argv` arguments are now only parsed if
+ :c:member:`PyConfig.parse_argv` equals to ``1``.
- /* Set the program name before reading the configuration
- (decode byte string from the locale encoding).
+ .. c:member:: int parser_debug
- Implicitly preinitialize Python. */
- status = PyConfig_SetBytesString(&config, &config.program_name,
- program_name);
- if (PyStatus_Exception(status)) {
- goto done;
- }
+ Parser debug mode. If greater than ``0``, turn on parser debugging output (for expert only, depending
+ on compilation options).
- /* Read all configuration at once */
- status = PyConfig_Read(&config);
- if (PyStatus_Exception(status)) {
- goto done;
- }
+ Incremented by the :option:`-d` command line option. Set to the
+ :envvar:`PYTHONDEBUG` environment variable value.
- /* Specify sys.path explicitly */
- /* If you want to modify the default set of paths, finish
- initialization first and then use PySys_GetObject("path") */
- config.module_search_paths_set = 1;
- status = PyWideStringList_Append(&config.module_search_paths,
- L"/path/to/stdlib");
- if (PyStatus_Exception(status)) {
- goto done;
- }
- status = PyWideStringList_Append(&config.module_search_paths,
- L"/path/to/more/modules");
- if (PyStatus_Exception(status)) {
- goto done;
- }
+ Needs a :ref:`debug build of Python <debug-build>` (the ``Py_DEBUG`` macro
+ must be defined).
- /* Override executable computed by PyConfig_Read() */
- status = PyConfig_SetString(&config, &config.executable,
- L"/path/to/my_executable");
- if (PyStatus_Exception(status)) {
- goto done;
- }
+ Default: ``0``.
- status = Py_InitializeFromConfig(&config);
+ .. c:member:: int pathconfig_warnings
- done:
- PyConfig_Clear(&config);
- return status;
- }
+ If non-zero, calculation of path configuration is allowed to log
+ warnings into ``stderr``. If equals to ``0``, suppress these warnings.
+ Default: ``1`` in Python mode, ``0`` in isolated mode.
-.. _init-isolated-conf:
+ Part of the :ref:`Python Path Configuration <init-path-config>` input.
-Isolated Configuration
-----------------------
+ .. versionchanged:: 3.11
+ Now also applies on Windows.
-:c:func:`PyPreConfig_InitIsolatedConfig` and
-:c:func:`PyConfig_InitIsolatedConfig` functions create a configuration to
-isolate Python from the system. For example, to embed Python into an
-application.
+ .. c:member:: wchar_t* prefix
-This configuration ignores global configuration variables, environment
-variables, command line arguments (:c:member:`PyConfig.argv` is not parsed)
-and user site directory. The C standard streams (ex: ``stdout``) and the
-LC_CTYPE locale are left unchanged. Signal handlers are not installed.
-
-Configuration files are still used with this configuration to determine
-paths that are unspecified. Ensure :c:member:`PyConfig.home` is specified
-to avoid computing the default path configuration.
+ The site-specific directory prefix where the platform independent Python
+ files are installed: :data:`sys.prefix`.
+ Default: ``NULL``.
-.. _init-python-config:
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
-Python Configuration
---------------------
+ See also :c:member:`PyConfig.base_prefix`.
-:c:func:`PyPreConfig_InitPythonConfig` and :c:func:`PyConfig_InitPythonConfig`
-functions create a configuration to build a customized Python which behaves as
-the regular Python.
+ .. c:member:: wchar_t* program_name
-Environments variables and command line arguments are used to configure
-Python, whereas global configuration variables are ignored.
+ Program name used to initialize :c:member:`~PyConfig.executable` and in
+ early error messages during Python initialization.
-This function enables C locale coercion (:pep:`538`)
-and :ref:`Python UTF-8 Mode <utf8-mode>`
-(:pep:`540`) depending on the LC_CTYPE locale, :envvar:`PYTHONUTF8` and
-:envvar:`PYTHONCOERCECLOCALE` environment variables.
+ * 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.
+ * Use ``argv[0]`` of :c:member:`~PyConfig.argv` if available and
+ non-empty.
+ * Otherwise, use ``L"python"`` on Windows, or ``L"python3"`` on other
+ platforms.
+ Default: ``NULL``.
-.. _init-path-config:
+ Part of the :ref:`Python Path Configuration <init-path-config>` input.
-Python Path Configuration
--------------------------
+ .. c:member:: wchar_t* pycache_prefix
-:c:type:`PyConfig` contains multiple fields for the path configuration:
+ Directory where cached ``.pyc`` files are written:
+ :data:`sys.pycache_prefix`.
-* Path configuration inputs:
+ Set by the :option:`-X pycache_prefix=PATH <-X>` command line option and
+ the :envvar:`PYTHONPYCACHEPREFIX` environment variable.
+ The command-line option takes precedence.
- * :c:member:`PyConfig.home`
- * :c:member:`PyConfig.platlibdir`
- * :c:member:`PyConfig.pathconfig_warnings`
- * :c:member:`PyConfig.program_name`
- * :c:member:`PyConfig.pythonpath_env`
- * current working directory: to get absolute paths
- * ``PATH`` environment variable to get the program full path
- (from :c:member:`PyConfig.program_name`)
- * ``__PYVENV_LAUNCHER__`` environment variable
- * (Windows only) Application paths in the registry under
- "Software\Python\PythonCore\X.Y\PythonPath" of HKEY_CURRENT_USER and
- HKEY_LOCAL_MACHINE (where X.Y is the Python version).
+ If ``NULL``, :data:`sys.pycache_prefix` is set to ``None``.
-* Path configuration output fields:
+ Default: ``NULL``.
- * :c:member:`PyConfig.base_exec_prefix`
- * :c:member:`PyConfig.base_executable`
- * :c:member:`PyConfig.base_prefix`
- * :c:member:`PyConfig.exec_prefix`
- * :c:member:`PyConfig.executable`
- * :c:member:`PyConfig.module_search_paths_set`,
- :c:member:`PyConfig.module_search_paths`
- * :c:member:`PyConfig.prefix`
+ .. c:member:: int quiet
-If at least one "output field" is not set, Python calculates the path
-configuration to fill unset fields. If
-:c:member:`~PyConfig.module_search_paths_set` is equal to ``0``,
-:c:member:`~PyConfig.module_search_paths` is overridden and
-:c:member:`~PyConfig.module_search_paths_set` is set to ``1``.
+ Quiet mode. If greater than ``0``, don't display the copyright and version at
+ Python startup in interactive mode.
-It is possible to completely ignore the function calculating the default
-path configuration by setting explicitly all path configuration output
-fields listed above. A string is considered as set even if it is non-empty.
-``module_search_paths`` is considered as set if
-``module_search_paths_set`` is set to ``1``. In this case,
-``module_search_paths`` will be used without modification.
+ Incremented by the :option:`-q` command line option.
-Set :c:member:`~PyConfig.pathconfig_warnings` to ``0`` to suppress warnings when
-calculating the path configuration (Unix only, Windows does not log any warning).
+ Default: ``0``.
-If :c:member:`~PyConfig.base_prefix` or :c:member:`~PyConfig.base_exec_prefix`
-fields are not set, they inherit their value from :c:member:`~PyConfig.prefix`
-and :c:member:`~PyConfig.exec_prefix` respectively.
+ .. c:member:: wchar_t* run_command
-:c:func:`Py_RunMain` and :c:func:`Py_Main` modify :data:`sys.path`:
+ Value of the :option:`-c` command line option.
-* If :c:member:`~PyConfig.run_filename` is set and is a directory which contains a
- ``__main__.py`` script, prepend :c:member:`~PyConfig.run_filename` to
- :data:`sys.path`.
-* If :c:member:`~PyConfig.isolated` is zero:
+ Used by :c:func:`Py_RunMain`.
- * If :c:member:`~PyConfig.run_module` is set, prepend the current directory
- to :data:`sys.path`. Do nothing if the current directory cannot be read.
- * If :c:member:`~PyConfig.run_filename` is set, prepend the directory of the
- filename to :data:`sys.path`.
- * Otherwise, prepend an empty string to :data:`sys.path`.
+ Default: ``NULL``.
-If :c:member:`~PyConfig.site_import` is non-zero, :data:`sys.path` can be
-modified by the :mod:`site` module. If
-:c:member:`~PyConfig.user_site_directory` is non-zero and the user's
-site-package directory exists, the :mod:`site` module appends the user's
-site-package directory to :data:`sys.path`.
+ .. c:member:: wchar_t* run_filename
-The following configuration files are used by the path configuration:
+ Filename passed on the command line: trailing command line argument
+ without :option:`-c` or :option:`-m`. It is used by the
+ :c:func:`Py_RunMain` function.
-* ``pyvenv.cfg``
-* ``._pth`` file (ex: ``python._pth``)
-* ``pybuilddir.txt`` (Unix only)
+ For example, it is set to ``script.py`` by the ``python3 script.py arg``
+ command line.
-If a ``._pth`` file is present:
+ See also the :c:member:`PyConfig.skip_source_first_line` option.
-* Set :c:member:`~PyConfig.isolated` to ``1``.
-* Set :c:member:`~PyConfig.use_environment` to ``0``.
-* Set :c:member:`~PyConfig.site_import` to ``0``.
-* Set :c:member:`~PyConfig.safe_path` to ``1``.
+ Default: ``NULL``.
-If :c:member:`~PyConfig.home` is not set and a ``pyvenv.cfg`` file is present in
-the same directory as :c:member:`~PyConfig.executable`, or its parent,
-:c:member:`~PyConfig.prefix` and :c:member:`~PyConfig.exec_prefix` are set that
-location. When this happens, :c:member:`~PyConfig.base_prefix` and
-:c:member:`~PyConfig.base_exec_prefix` still keep their value, pointing to the
-base installation. See :ref:`sys-path-init-virtual-environments` for more
-information.
+ .. c:member:: wchar_t* run_module
-The ``__PYVENV_LAUNCHER__`` environment variable is used to set
-:c:member:`PyConfig.base_executable`.
+ Value of the :option:`-m` command line option.
-.. versionchanged:: 3.14
+ Used by :c:func:`Py_RunMain`.
- :c:member:`~PyConfig.prefix`, and :c:member:`~PyConfig.exec_prefix`, are now
- set to the ``pyvenv.cfg`` directory. This was previously done by :mod:`site`,
- therefore affected by :option:`-S`.
+ Default: ``NULL``.
-.. _pyinitconfig_api:
+ .. c:member:: wchar_t* run_presite
-PyInitConfig C API
-==================
+ ``package.module`` path to module that should be imported before
+ ``site.py`` is run.
-C API to configure the Python initialization (:pep:`741`).
+ Set by the :option:`-X presite=package.module <-X>` command-line
+ option and the :envvar:`PYTHON_PRESITE` environment variable.
+ The command-line option takes precedence.
-.. versionadded:: 3.14
+ Needs a :ref:`debug build of Python <debug-build>` (the ``Py_DEBUG`` macro
+ must be defined).
-Create Config
--------------
+ Default: ``NULL``.
-.. c:struct:: PyInitConfig
+ .. c:member:: int show_ref_count
- Opaque structure to configure the Python initialization.
+ Show total reference count at exit (excluding :term:`immortal` objects)?
+ Set to ``1`` by :option:`-X showrefcount <-X>` command line option.
-.. c:function:: PyInitConfig* PyInitConfig_Create(void)
+ Needs a :ref:`debug build of Python <debug-build>` (the ``Py_REF_DEBUG``
+ macro must be defined).
- Create a new initialization configuration using :ref:`Isolated Configuration
- <init-isolated-conf>` default values.
+ Default: ``0``.
- It must be freed by :c:func:`PyInitConfig_Free`.
+ .. c:member:: int site_import
- Return ``NULL`` on memory allocation failure.
+ Import the :mod:`site` module at startup?
+ If equal to zero, disable the import of the module site and the
+ site-dependent manipulations of :data:`sys.path` that it entails.
-.. c:function:: void PyInitConfig_Free(PyInitConfig *config)
+ Also disable these manipulations if the :mod:`site` module is explicitly
+ imported later (call :func:`site.main` if you want them to be triggered).
- Free memory of the initialization configuration *config*.
+ Set to ``0`` by the :option:`-S` command line option.
- If *config* is ``NULL``, no operation is performed.
+ :data:`sys.flags.no_site <sys.flags>` is set to the inverted value of
+ :c:member:`~PyConfig.site_import`.
+ Default: ``1``.
-Error Handling
---------------
+ .. c:member:: int skip_source_first_line
-.. c:function:: int PyInitConfig_GetError(PyInitConfig* config, const char **err_msg)
+ If non-zero, skip the first line of the :c:member:`PyConfig.run_filename`
+ source.
- Get the *config* error message.
+ It allows the usage of non-Unix forms of ``#!cmd``. This is intended for
+ a DOS specific hack only.
- * Set *\*err_msg* and return ``1`` if an error is set.
- * Set *\*err_msg* to ``NULL`` and return ``0`` otherwise.
+ Set to ``1`` by the :option:`-x` command line option.
- An error message is an UTF-8 encoded string.
+ Default: ``0``.
- If *config* has an exit code, format the exit code as an error
- message.
+ .. c:member:: wchar_t* stdio_encoding
+ .. c:member:: wchar_t* stdio_errors
- The error message remains valid until another ``PyInitConfig``
- function is called with *config*. The caller doesn't have to free the
- error message.
+ Encoding and encoding errors of :data:`sys.stdin`, :data:`sys.stdout` and
+ :data:`sys.stderr` (but :data:`sys.stderr` always uses
+ ``"backslashreplace"`` error handler).
+ Use the :envvar:`PYTHONIOENCODING` environment variable if it is
+ non-empty.
-.. c:function:: int PyInitConfig_GetExitCode(PyInitConfig* config, int *exitcode)
+ Default encoding:
- Get the *config* exit code.
+ * ``"UTF-8"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero.
+ * Otherwise, use the :term:`locale encoding`.
- * Set *\*exitcode* and return ``1`` if *config* has an exit code set.
- * Return ``0`` if *config* has no exit code set.
+ Default error handler:
- Only the ``Py_InitializeFromInitConfig()`` function can set an exit
- code if the ``parse_argv`` option is non-zero.
+ * On Windows: use ``"surrogateescape"``.
+ * ``"surrogateescape"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero,
+ or if the LC_CTYPE locale is "C" or "POSIX".
+ * ``"strict"`` otherwise.
- 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``).
+ See also :c:member:`PyConfig.legacy_windows_stdio`.
+ .. c:member:: int tracemalloc
-Get Options
------------
+ Enable tracemalloc?
-The configuration option *name* parameter must be a non-NULL
-null-terminated UTF-8 encoded string.
+ If non-zero, call :func:`tracemalloc.start` at startup.
-.. c:function:: int PyInitConfig_HasOption(PyInitConfig *config, const char *name)
+ Set by :option:`-X tracemalloc=N <-X>` command line option and by the
+ :envvar:`PYTHONTRACEMALLOC` environment variable.
- Test if the configuration has an option called *name*.
+ Default: ``-1`` in Python mode, ``0`` in isolated mode.
- Return ``1`` if the option exists, or return ``0`` otherwise.
+ .. c:member:: int perf_profiling
+ Enable the Linux ``perf`` profiler support?
-.. c:function:: int PyInitConfig_GetInt(PyInitConfig *config, const char *name, int64_t *value)
+ If equals to ``1``, enable support for the Linux ``perf`` profiler.
- Get an integer configuration option.
+ If equals to ``2``, enable support for the Linux ``perf`` profiler with
+ DWARF JIT support.
- * Set *\*value*, and return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ Set to ``1`` by :option:`-X perf <-X>` command-line option and the
+ :envvar:`PYTHONPERFSUPPORT` environment variable.
+ Set to ``2`` by the :option:`-X perf_jit <-X>` command-line option and
+ the :envvar:`PYTHON_PERF_JIT_SUPPORT` environment variable.
-.. c:function:: int PyInitConfig_GetStr(PyInitConfig *config, const char *name, char **value)
+ Default: ``-1``.
- Get a string configuration option as a null-terminated UTF-8
- encoded string.
+ .. seealso::
+ See :ref:`perf_profiling` for more information.
- * Set *\*value*, and return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ .. versionadded:: 3.12
- *\*value* can be set to ``NULL`` if the option is an optional string and the
- option is unset.
+ .. c:member:: int use_environment
- On success, the string must be released with ``free(value)`` if it's not
- ``NULL``.
+ Use :ref:`environment variables <using-on-envvars>`?
+ If equals to zero, ignore the :ref:`environment variables
+ <using-on-envvars>`.
-.. c:function:: int PyInitConfig_GetStrList(PyInitConfig *config, const char *name, size_t *length, char ***items)
+ Set to ``0`` by the :option:`-E` environment variable.
- Get a string list configuration option as an array of
- null-terminated UTF-8 encoded strings.
+ Default: ``1`` in Python config and ``0`` in isolated config.
- * Set *\*length* and *\*value*, and return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ .. c:member:: int use_system_logger
- On success, the string list must be released with
- ``PyInitConfig_FreeStrList(length, items)``.
+ If non-zero, ``stdout`` and ``stderr`` will be redirected to the system
+ log.
+ Only available on macOS 10.12 and later, and on iOS.
-.. c:function:: void PyInitConfig_FreeStrList(size_t length, char **items)
+ Default: ``0`` (don't use system log).
- Free memory of a string list created by
- ``PyInitConfig_GetStrList()``.
+ .. versionadded:: 3.13.2
+ .. c:member:: int user_site_directory
-Set Options
------------
+ If non-zero, add the user site directory to :data:`sys.path`.
-The configuration option *name* parameter must be a non-NULL null-terminated
-UTF-8 encoded string.
+ Set to ``0`` by the :option:`-s` and :option:`-I` command line options.
-Some configuration options have side effects on other options. This logic is
-only implemented when ``Py_InitializeFromInitConfig()`` is called, not by the
-"Set" functions below. For example, setting ``dev_mode`` to ``1`` does not set
-``faulthandler`` to ``1``.
+ Set to ``0`` by the :envvar:`PYTHONNOUSERSITE` environment variable.
-.. c:function:: int PyInitConfig_SetInt(PyInitConfig *config, const char *name, int64_t value)
+ Default: ``1`` in Python mode, ``0`` in isolated mode.
- Set an integer configuration option.
+ .. c:member:: int verbose
- * Return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ Verbose mode. If greater than ``0``, print a message each time a module is
+ imported, showing the place (filename or built-in module) from which
+ it is loaded.
+ If greater than or equal to ``2``, print a message for each file that is
+ checked for when searching for a module. Also provides information on
+ module cleanup at exit.
-.. c:function:: int PyInitConfig_SetStr(PyInitConfig *config, const char *name, const char *value)
+ Incremented by the :option:`-v` command line option.
- Set a string configuration option from a null-terminated UTF-8
- encoded string. The string is copied.
+ Set by the :envvar:`PYTHONVERBOSE` environment variable value.
- * Return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ Default: ``0``.
+ .. c:member:: PyWideStringList warnoptions
-.. c:function:: int PyInitConfig_SetStrList(PyInitConfig *config, const char *name, size_t length, char * const *items)
+ Options of the :mod:`warnings` module to build warnings filters, lowest
+ to highest priority: :data:`sys.warnoptions`.
- Set a string list configuration option from an array of
- null-terminated UTF-8 encoded strings. The string list is copied.
+ The :mod:`warnings` module adds :data:`sys.warnoptions` in the reverse
+ order: the last :c:member:`PyConfig.warnoptions` item becomes the first
+ item of :data:`warnings.filters` which is checked first (highest
+ priority).
- * Return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ The :option:`-W` command line options adds its value to
+ :c:member:`~PyConfig.warnoptions`, it can be used multiple times.
+ The :envvar:`PYTHONWARNINGS` environment variable can also be used to add
+ warning options. Multiple options can be specified, separated by commas
+ (``,``).
-Module
-------
+ Default: empty list.
-.. c:function:: int PyInitConfig_AddModule(PyInitConfig *config, const char *name, PyObject* (*initfunc)(void))
+ .. c:member:: int write_bytecode
- Add a built-in extension module to the table of built-in modules.
+ If equal to ``0``, Python won't try to write ``.pyc`` files on the import of
+ source modules.
- The new module can be imported by the name *name*, and uses the function
- *initfunc* as the initialization function called on the first attempted
- import.
+ Set to ``0`` by the :option:`-B` command line option and the
+ :envvar:`PYTHONDONTWRITEBYTECODE` environment variable.
- * Return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ :data:`sys.dont_write_bytecode` is initialized to the inverted value of
+ :c:member:`~PyConfig.write_bytecode`.
- If Python is initialized multiple times, ``PyInitConfig_AddModule()`` must
- be called at each Python initialization.
+ Default: ``1``.
- Similar to the :c:func:`PyImport_AppendInittab` function.
+ .. c:member:: PyWideStringList xoptions
+ Values of the :option:`-X` command line options: :data:`sys._xoptions`.
-Initialize Python
------------------
+ Default: empty list.
-.. c:function:: int Py_InitializeFromInitConfig(PyInitConfig *config)
+If :c:member:`~PyConfig.parse_argv` is non-zero, :c:member:`~PyConfig.argv`
+arguments are parsed the same way the regular Python parses :ref:`command line
+arguments <using-on-cmdline>`, and Python arguments are stripped from
+:c:member:`~PyConfig.argv`.
- Initialize Python from the initialization configuration.
+The :c:member:`~PyConfig.xoptions` options are parsed to set other options: see
+the :option:`-X` command line option.
- * 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.
+.. versionchanged:: 3.9
- See ``PyInitConfig_GetExitcode()`` for the exit code case.
+ The ``show_alloc_count`` field has been removed.
-Example
--------
+.. _init-from-config:
-Example initializing Python, set configuration options of various types,
-return ``-1`` on error:
+Initialization with PyConfig
+----------------------------
-.. code-block:: c
+Initializing the interpreter from a populated configuration struct is handled
+by calling :c:func:`Py_InitializeFromConfig`.
- int init_python(void)
+The caller is responsible to handle exceptions (error or exit) using
+:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`.
+
+If :c:func:`PyImport_FrozenModules`, :c:func:`PyImport_AppendInittab` or
+:c:func:`PyImport_ExtendInittab` are used, they must be set or called after
+Python preinitialization and before the Python initialization. If Python is
+initialized multiple times, :c:func:`PyImport_AppendInittab` or
+:c:func:`PyImport_ExtendInittab` must be called before each Python
+initialization.
+
+The current configuration (``PyConfig`` type) is stored in
+``PyInterpreterState.config``.
+
+Example setting the program name::
+
+ void init_python(void)
{
- PyInitConfig *config = PyInitConfig_Create();
- if (config == NULL) {
- printf("PYTHON INIT ERROR: memory allocation failed\n");
- return -1;
- }
+ PyStatus status;
- // Set an integer (dev mode)
- if (PyInitConfig_SetInt(config, "dev_mode", 1) < 0) {
- goto error;
+ PyConfig config;
+ PyConfig_InitPythonConfig(&config);
+
+ /* Set the program name. Implicitly preinitialize Python. */
+ status = PyConfig_SetString(&config, &config.program_name,
+ L"/path/to/my_program");
+ if (PyStatus_Exception(status)) {
+ goto exception;
}
- // Set a list of UTF-8 strings (argv)
- char *argv[] = {"my_program", "-c", "pass"};
- if (PyInitConfig_SetStrList(config, "argv",
- Py_ARRAY_LENGTH(argv), argv) < 0) {
- goto error;
+ status = Py_InitializeFromConfig(&config);
+ if (PyStatus_Exception(status)) {
+ goto exception;
}
+ PyConfig_Clear(&config);
+ return;
- // Set a UTF-8 string (program name)
- if (PyInitConfig_SetStr(config, "program_name", L"my_program") < 0) {
- goto error;
+ exception:
+ PyConfig_Clear(&config);
+ Py_ExitStatusException(status);
+ }
+
+More complete example modifying the default configuration, read the
+configuration, and then override some parameters. Note that since
+3.11, many parameters are not calculated until initialization, and
+so values cannot be read from the configuration structure. Any values
+set before initialize is called will be left unchanged by
+initialization::
+
+ PyStatus init_python(const char *program_name)
+ {
+ PyStatus status;
+
+ PyConfig config;
+ PyConfig_InitPythonConfig(&config);
+
+ /* Set the program name before reading the configuration
+ (decode byte string from the locale encoding).
+
+ Implicitly preinitialize Python. */
+ status = PyConfig_SetBytesString(&config, &config.program_name,
+ program_name);
+ if (PyStatus_Exception(status)) {
+ goto done;
}
- // Initialize Python with the configuration
- if (Py_InitializeFromInitConfig(config) < 0) {
- goto error;
+ /* Read all configuration at once */
+ status = PyConfig_Read(&config);
+ if (PyStatus_Exception(status)) {
+ goto done;
}
- PyInitConfig_Free(config);
- return 0;
- error:
- {
- // Display the error message
- // This uncommon braces style is used, because you cannot make
- // goto targets point to variable declarations.
- const char *err_msg;
- (void)PyInitConfig_GetError(config, &err_msg);
- printf("PYTHON INIT ERROR: %s\n", err_msg);
- PyInitConfig_Free(config);
+ /* Specify sys.path explicitly */
+ /* If you want to modify the default set of paths, finish
+ initialization first and then use PySys_GetObject("path") */
+ config.module_search_paths_set = 1;
+ status = PyWideStringList_Append(&config.module_search_paths,
+ L"/path/to/stdlib");
+ if (PyStatus_Exception(status)) {
+ goto done;
+ }
+ status = PyWideStringList_Append(&config.module_search_paths,
+ L"/path/to/more/modules");
+ if (PyStatus_Exception(status)) {
+ goto done;
+ }
- return -1;
+ /* Override executable computed by PyConfig_Read() */
+ status = PyConfig_SetString(&config, &config.executable,
+ L"/path/to/my_executable");
+ if (PyStatus_Exception(status)) {
+ goto done;
}
+
+ status = Py_InitializeFromConfig(&config);
+
+ done:
+ PyConfig_Clear(&config);
+ return status;
}
-Runtime Python configuration API
-================================
+.. _init-isolated-conf:
-The configuration option *name* parameter must be a non-NULL null-terminated
-UTF-8 encoded string.
+Isolated Configuration
+----------------------
-Some options are read from the :mod:`sys` attributes. For example, the option
-``"argv"`` is read from :data:`sys.argv`.
+:c:func:`PyPreConfig_InitIsolatedConfig` and
+:c:func:`PyConfig_InitIsolatedConfig` functions create a configuration to
+isolate Python from the system. For example, to embed Python into an
+application.
+This configuration ignores global configuration variables, environment
+variables, command line arguments (:c:member:`PyConfig.argv` is not parsed)
+and user site directory. The C standard streams (ex: ``stdout``) and the
+LC_CTYPE locale are left unchanged. Signal handlers are not installed.
-.. c:function:: PyObject* PyConfig_Get(const char *name)
+Configuration files are still used with this configuration to determine
+paths that are unspecified. Ensure :c:member:`PyConfig.home` is specified
+to avoid computing the default path configuration.
- Get the current runtime value of a configuration option as a Python object.
- * Return a new reference on success.
- * Set an exception and return ``NULL`` on error.
+.. _init-python-config:
- The object type depends on the configuration option. It can be:
+Python Configuration
+--------------------
- * ``bool``
- * ``int``
- * ``str``
- * ``list[str]``
- * ``dict[str, str]``
+:c:func:`PyPreConfig_InitPythonConfig` and :c:func:`PyConfig_InitPythonConfig`
+functions create a configuration to build a customized Python which behaves as
+the regular Python.
- The caller must hold the GIL. The function cannot be called before
- Python initialization nor after Python finalization.
+Environments variables and command line arguments are used to configure
+Python, whereas global configuration variables are ignored.
- .. versionadded:: 3.14
+This function enables C locale coercion (:pep:`538`)
+and :ref:`Python UTF-8 Mode <utf8-mode>`
+(:pep:`540`) depending on the LC_CTYPE locale, :envvar:`PYTHONUTF8` and
+:envvar:`PYTHONCOERCECLOCALE` environment variables.
-.. c:function:: int PyConfig_GetInt(const char *name, int *value)
+.. _init-path-config:
- Similar to :c:func:`PyConfig_Get`, but get the value as a C int.
+Python Path Configuration
+-------------------------
- * Return ``0`` on success.
- * Set an exception and return ``-1`` on error.
+:c:type:`PyConfig` contains multiple fields for the path configuration:
- .. versionadded:: 3.14
+* Path configuration inputs:
+ * :c:member:`PyConfig.home`
+ * :c:member:`PyConfig.platlibdir`
+ * :c:member:`PyConfig.pathconfig_warnings`
+ * :c:member:`PyConfig.program_name`
+ * :c:member:`PyConfig.pythonpath_env`
+ * current working directory: to get absolute paths
+ * ``PATH`` environment variable to get the program full path
+ (from :c:member:`PyConfig.program_name`)
+ * ``__PYVENV_LAUNCHER__`` environment variable
+ * (Windows only) Application paths in the registry under
+ "Software\Python\PythonCore\X.Y\PythonPath" of HKEY_CURRENT_USER and
+ HKEY_LOCAL_MACHINE (where X.Y is the Python version).
-.. c:function:: PyObject* PyConfig_Names(void)
+* Path configuration output fields:
- Get all configuration option names as a ``frozenset``.
+ * :c:member:`PyConfig.base_exec_prefix`
+ * :c:member:`PyConfig.base_executable`
+ * :c:member:`PyConfig.base_prefix`
+ * :c:member:`PyConfig.exec_prefix`
+ * :c:member:`PyConfig.executable`
+ * :c:member:`PyConfig.module_search_paths_set`,
+ :c:member:`PyConfig.module_search_paths`
+ * :c:member:`PyConfig.prefix`
- * Return a new reference on success.
- * Set an exception and return ``NULL`` on error.
+If at least one "output field" is not set, Python calculates the path
+configuration to fill unset fields. If
+:c:member:`~PyConfig.module_search_paths_set` is equal to ``0``,
+:c:member:`~PyConfig.module_search_paths` is overridden and
+:c:member:`~PyConfig.module_search_paths_set` is set to ``1``.
- The caller must hold the GIL. The function cannot be called before
- Python initialization nor after Python finalization.
+It is possible to completely ignore the function calculating the default
+path configuration by setting explicitly all path configuration output
+fields listed above. A string is considered as set even if it is non-empty.
+``module_search_paths`` is considered as set if
+``module_search_paths_set`` is set to ``1``. In this case,
+``module_search_paths`` will be used without modification.
- .. versionadded:: 3.14
+Set :c:member:`~PyConfig.pathconfig_warnings` to ``0`` to suppress warnings when
+calculating the path configuration (Unix only, Windows does not log any warning).
+If :c:member:`~PyConfig.base_prefix` or :c:member:`~PyConfig.base_exec_prefix`
+fields are not set, they inherit their value from :c:member:`~PyConfig.prefix`
+and :c:member:`~PyConfig.exec_prefix` respectively.
-.. c:function:: int PyConfig_Set(const char *name, PyObject *value)
+:c:func:`Py_RunMain` and :c:func:`Py_Main` modify :data:`sys.path`:
- Set the current runtime value of a configuration option.
+* If :c:member:`~PyConfig.run_filename` is set and is a directory which contains a
+ ``__main__.py`` script, prepend :c:member:`~PyConfig.run_filename` to
+ :data:`sys.path`.
+* If :c:member:`~PyConfig.isolated` is zero:
- * Raise a :exc:`ValueError` if there is no option *name*.
- * Raise a :exc:`ValueError` if *value* is an invalid value.
- * Raise a :exc:`ValueError` if the option is read-only (cannot be set).
- * Raise a :exc:`TypeError` if *value* has not the proper type.
+ * If :c:member:`~PyConfig.run_module` is set, prepend the current directory
+ to :data:`sys.path`. Do nothing if the current directory cannot be read.
+ * If :c:member:`~PyConfig.run_filename` is set, prepend the directory of the
+ filename to :data:`sys.path`.
+ * Otherwise, prepend an empty string to :data:`sys.path`.
- The caller must hold the GIL. The function cannot be called before
- Python initialization nor after Python finalization.
+If :c:member:`~PyConfig.site_import` is non-zero, :data:`sys.path` can be
+modified by the :mod:`site` module. If
+:c:member:`~PyConfig.user_site_directory` is non-zero and the user's
+site-package directory exists, the :mod:`site` module appends the user's
+site-package directory to :data:`sys.path`.
- .. versionadded:: 3.14
+The following configuration files are used by the path configuration:
+
+* ``pyvenv.cfg``
+* ``._pth`` file (ex: ``python._pth``)
+* ``pybuilddir.txt`` (Unix only)
+
+If a ``._pth`` file is present:
+
+* Set :c:member:`~PyConfig.isolated` to ``1``.
+* Set :c:member:`~PyConfig.use_environment` to ``0``.
+* Set :c:member:`~PyConfig.site_import` to ``0``.
+* Set :c:member:`~PyConfig.safe_path` to ``1``.
+
+If :c:member:`~PyConfig.home` is not set and a ``pyvenv.cfg`` file is present in
+the same directory as :c:member:`~PyConfig.executable`, or its parent,
+:c:member:`~PyConfig.prefix` and :c:member:`~PyConfig.exec_prefix` are set that
+location. When this happens, :c:member:`~PyConfig.base_prefix` and
+:c:member:`~PyConfig.base_exec_prefix` still keep their value, pointing to the
+base installation. See :ref:`sys-path-init-virtual-environments` for more
+information.
+
+The ``__PYVENV_LAUNCHER__`` environment variable is used to set
+:c:member:`PyConfig.base_executable`.
+
+.. versionchanged:: 3.14
+
+ :c:member:`~PyConfig.prefix`, and :c:member:`~PyConfig.exec_prefix`, are now
+ set to the ``pyvenv.cfg`` directory. This was previously done by :mod:`site`,
+ therefore affected by :option:`-S`.
Py_GetArgcArgv()
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/0351ed50499c3d7fbefe126d025d32eb86…
commit: 0351ed50499c3d7fbefe126d025d32eb865ad3f0
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: Eclips4 <kirill.bast9(a)mail.ru>
date: 2025-01-20T10:37:21Z
summary:
[3.13] Fix a typo in `syslog`'s error message (GH-129029) (#129049)
Fix a typo in `syslog`'s error message (GH-129029)
(cherry picked from commit 9b1c1817af30e609b7cbfacbe5b1e73e21dc9e37)
Co-authored-by: Tomas R <tomas.roun8(a)gmail.com>
files:
M Modules/syslogmodule.c
diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c
index 14e7ca591a076b..adbd2fcc6ed74d 100644
--- a/Modules/syslogmodule.c
+++ b/Modules/syslogmodule.c
@@ -258,7 +258,7 @@ syslog_closelog_impl(PyObject *module)
// Since the sys.closelog changes the process level state of syslog library,
// this operation is only allowed for the main interpreter.
if (!is_main_interpreter()) {
- PyErr_SetString(PyExc_RuntimeError, "sunbinterpreter can't use syslog.closelog()");
+ PyErr_SetString(PyExc_RuntimeError, "subinterpreter can't use syslog.closelog()");
return NULL;
}
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/7f68e7bf2a768489ece13054d0cf9566d1…
commit: 7f68e7bf2a768489ece13054d0cf9566d176c576
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: Eclips4 <kirill.bast9(a)mail.ru>
date: 2025-01-20T10:28:55Z
summary:
[3.12] Fix a typo in `syslog`'s error message (GH-129029) (#129050)
Fix a typo in `syslog`'s error message (GH-129029)
(cherry picked from commit 9b1c1817af30e609b7cbfacbe5b1e73e21dc9e37)
Co-authored-by: Tomas R <tomas.roun8(a)gmail.com>
files:
M Modules/syslogmodule.c
diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c
index 6db8de9c491dd9..722364e0751d9f 100644
--- a/Modules/syslogmodule.c
+++ b/Modules/syslogmodule.c
@@ -250,7 +250,7 @@ syslog_closelog_impl(PyObject *module)
// Since the sys.closelog changes the process level state of syslog library,
// this operation is only allowed for the main interpreter.
if (!is_main_interpreter()) {
- PyErr_SetString(PyExc_RuntimeError, "sunbinterpreter can't use syslog.closelog()");
+ PyErr_SetString(PyExc_RuntimeError, "subinterpreter can't use syslog.closelog()");
return NULL;
}
1
0
https://github.com/python/cpython/commit/9b1c1817af30e609b7cbfacbe5b1e73e21…
commit: 9b1c1817af30e609b7cbfacbe5b1e73e21dc9e37
branch: main
author: Tomas R. <tomas.roun8(a)gmail.com>
committer: Eclips4 <kirill.bast9(a)mail.ru>
date: 2025-01-20T10:11:08Z
summary:
Fix a typo in `syslog`'s error message (#129029)
files:
M Modules/syslogmodule.c
diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c
index 14e7ca591a076b..adbd2fcc6ed74d 100644
--- a/Modules/syslogmodule.c
+++ b/Modules/syslogmodule.c
@@ -258,7 +258,7 @@ syslog_closelog_impl(PyObject *module)
// Since the sys.closelog changes the process level state of syslog library,
// this operation is only allowed for the main interpreter.
if (!is_main_interpreter()) {
- PyErr_SetString(PyExc_RuntimeError, "sunbinterpreter can't use syslog.closelog()");
+ PyErr_SetString(PyExc_RuntimeError, "subinterpreter can't use syslog.closelog()");
return NULL;
}
1
0
https://github.com/python/cpython/commit/07c3518ffb27875b14a0f1637aa85f773f…
commit: 07c3518ffb27875b14a0f1637aa85f773ff2f9ff
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-20T10:03:22Z
summary:
gh-129033: Remove _Py_InitializeMain() function (#129034)
Co-authored-by: Alyssa Coghlan <ncoghlan(a)gmail.com>
files:
A Misc/NEWS.d/next/C_API/2025-01-19-23-17-58.gh-issue-129033.cpRivP.rst
M Doc/c-api/init_config.rst
M Doc/whatsnew/3.14.rst
M Include/cpython/pylifecycle.h
M Lib/test/test_embed.py
M Programs/_testembed.c
M Python/pylifecycle.c
diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst
index 6b33d93a9f2af9..85566631ca1676 100644
--- a/Doc/c-api/init_config.rst
+++ b/Doc/c-api/init_config.rst
@@ -1946,89 +1946,13 @@ Py_GetArgcArgv()
See also :c:member:`PyConfig.orig_argv` member.
+Delaying main module execution
+==============================
-Multi-Phase Initialization Private Provisional API
-==================================================
+In some embedding use cases, it may be desirable to separate interpreter initialization
+from the execution of the main module.
-This section is a private provisional API introducing multi-phase
-initialization, the core feature of :pep:`432`:
-
-* "Core" initialization phase, "bare minimum Python":
-
- * Builtin types;
- * Builtin exceptions;
- * Builtin and frozen modules;
- * The :mod:`sys` module is only partially initialized
- (ex: :data:`sys.path` doesn't exist yet).
-
-* "Main" initialization phase, Python is fully initialized:
-
- * Install and configure :mod:`importlib`;
- * Apply the :ref:`Path Configuration <init-path-config>`;
- * Install signal handlers;
- * Finish :mod:`sys` module initialization (ex: create :data:`sys.stdout`
- and :data:`sys.path`);
- * Enable optional features like :mod:`faulthandler` and :mod:`tracemalloc`;
- * Import the :mod:`site` module;
- * etc.
-
-Private provisional API:
-
-* :c:member:`PyConfig._init_main`: if set to ``0``,
- :c:func:`Py_InitializeFromConfig` stops at the "Core" initialization phase.
-
-.. c:function:: PyStatus _Py_InitializeMain(void)
-
- Move to the "Main" initialization phase, finish the Python initialization.
-
-No module is imported during the "Core" phase and the ``importlib`` module is
-not configured: the :ref:`Path Configuration <init-path-config>` is only
-applied during the "Main" phase. It may allow to customize Python in Python to
-override or tune the :ref:`Path Configuration <init-path-config>`, maybe
-install a custom :data:`sys.meta_path` importer or an import hook, etc.
-
-It may become possible to calculate the :ref:`Path Configuration
-<init-path-config>` in Python, after the Core phase and before the Main phase,
-which is one of the :pep:`432` motivation.
-
-The "Core" phase is not properly defined: what should be and what should
-not be available at this phase is not specified yet. The API is marked
-as private and provisional: the API can be modified or even be removed
-anytime until a proper public API is designed.
-
-Example running Python code between "Core" and "Main" initialization
-phases::
-
- void init_python(void)
- {
- PyStatus status;
-
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
- config._init_main = 0;
-
- /* ... customize 'config' configuration ... */
-
- status = Py_InitializeFromConfig(&config);
- PyConfig_Clear(&config);
- if (PyStatus_Exception(status)) {
- Py_ExitStatusException(status);
- }
-
- /* Use sys.stderr because sys.stdout is only created
- by _Py_InitializeMain() */
- int res = PyRun_SimpleString(
- "import sys; "
- "print('Run Python code before _Py_InitializeMain', "
- "file=sys.stderr)");
- if (res < 0) {
- exit(1);
- }
-
- /* ... put more configuration code here ... */
-
- status = _Py_InitializeMain();
- if (PyStatus_Exception(status)) {
- Py_ExitStatusException(status);
- }
- }
+This separation can be achieved by setting ``PyConfig.run_command`` to the empty
+string during initialization (to prevent the interpreter from dropping into the
+interactive prompt), and then subsequently executing the desired main module
+code using ``__main__.__dict__`` as the global namespace.
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index d6aa6b346417e5..7f149d5c03dfbb 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -1375,3 +1375,7 @@ Removed
* Creating :c:data:`immutable types <Py_TPFLAGS_IMMUTABLETYPE>` with mutable
bases was deprecated since 3.12 and now raises a :exc:`TypeError`.
+
+* Remove the private ``_Py_InitializeMain()`` function. It was a
+ :term:`provisional API` added to Python 3.8 by :pep:`587`.
+ (Contributed by Victor Stinner in :gh:`129033`.)
diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h
index e46dfe59ec4630..86ce6e6f79824a 100644
--- a/Include/cpython/pylifecycle.h
+++ b/Include/cpython/pylifecycle.h
@@ -25,9 +25,6 @@ PyAPI_FUNC(PyStatus) Py_PreInitializeFromArgs(
PyAPI_FUNC(PyStatus) Py_InitializeFromConfig(
const PyConfig *config);
-// Python 3.8 provisional API (PEP 587)
-PyAPI_FUNC(PyStatus) _Py_InitializeMain(void);
-
PyAPI_FUNC(int) Py_RunMain(void);
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index 1b55cd156d759d..a2400aa96c3ddd 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -1274,24 +1274,6 @@ def test_init_run_main(self):
}
self.check_all_configs("test_init_run_main", config, api=API_PYTHON)
- def test_init_main(self):
- code = ('import _testinternalcapi, json; '
- 'print(json.dumps(_testinternalcapi.get_configs()))')
- config = {
- 'argv': ['-c', 'arg2'],
- 'orig_argv': ['python3',
- '-c', code,
- 'arg2'],
- 'program_name': './python3',
- 'run_command': code + '\n',
- 'parse_argv': True,
- '_init_main': False,
- 'sys_path_0': '',
- }
- self.check_all_configs("test_init_main", config,
- api=API_PYTHON,
- stderr="Run Python code before _Py_InitializeMain")
-
def test_init_parse_argv(self):
config = {
'parse_argv': True,
@@ -1768,7 +1750,6 @@ def test_init_warnoptions(self):
def test_init_set_config(self):
config = {
- '_init_main': 0,
'bytes_warning': 2,
'warnoptions': ['error::BytesWarning'],
}
diff --git a/Misc/NEWS.d/next/C_API/2025-01-19-23-17-58.gh-issue-129033.cpRivP.rst b/Misc/NEWS.d/next/C_API/2025-01-19-23-17-58.gh-issue-129033.cpRivP.rst
new file mode 100644
index 00000000000000..3cd19cc48e3416
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2025-01-19-23-17-58.gh-issue-129033.cpRivP.rst
@@ -0,0 +1,3 @@
+Remove the private ``_Py_InitializeMain()`` function. It was a
+:term:`provisional API` added to Python 3.8 by :pep:`587`. Patch by Victor
+Stinner.
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
index d15dd519dbf6af..3681a89376638a 100644
--- a/Programs/_testembed.c
+++ b/Programs/_testembed.c
@@ -1818,7 +1818,6 @@ static int test_init_set_config(void)
PyConfig config;
PyConfig_InitIsolatedConfig(&config);
config_set_string(&config, &config.program_name, PROGRAM_NAME);
- config._init_main = 0;
config.bytes_warning = 0;
init_from_config_clear(&config);
@@ -1828,12 +1827,6 @@ static int test_init_set_config(void)
return 1;
}
- // Finish initialization: main part
- PyStatus status = _Py_InitializeMain();
- if (PyStatus_Exception(status)) {
- Py_ExitStatusException(status);
- }
-
dump_config();
Py_Finalize();
return 0;
@@ -2089,33 +2082,6 @@ static int test_init_run_main(void)
}
-static int test_init_main(void)
-{
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
-
- configure_init_main(&config);
- config._init_main = 0;
- init_from_config_clear(&config);
-
- /* sys.stdout don't exist yet: it is created by _Py_InitializeMain() */
- int res = PyRun_SimpleString(
- "import sys; "
- "print('Run Python code before _Py_InitializeMain', "
- "file=sys.stderr)");
- if (res < 0) {
- exit(1);
- }
-
- PyStatus status = _Py_InitializeMain();
- if (PyStatus_Exception(status)) {
- Py_ExitStatusException(status);
- }
-
- return Py_RunMain();
-}
-
-
static int test_run_main(void)
{
PyConfig config;
@@ -2473,7 +2439,6 @@ static struct TestCase TestCases[] = {
{"test_preinit_dont_parse_argv", test_preinit_dont_parse_argv},
{"test_init_read_set", test_init_read_set},
{"test_init_run_main", test_init_run_main},
- {"test_init_main", test_init_main},
{"test_init_sys_add", test_init_sys_add},
{"test_init_setpath", test_init_setpath},
{"test_init_setpath_config", test_init_setpath_config},
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index f1ecee6a92e5a1..8ec12b437f8298 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -1505,18 +1505,6 @@ Py_Initialize(void)
}
-PyStatus
-_Py_InitializeMain(void)
-{
- PyStatus status = _PyRuntime_Initialize();
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
- PyThreadState *tstate = _PyThreadState_GET();
- return pyinit_main(tstate);
-}
-
-
static void
finalize_modules_delete_special(PyThreadState *tstate, int verbose)
{
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/c463270c73a61ef8106ee7bd0571c7c614…
commit: c463270c73a61ef8106ee7bd0571c7c6143e2c20
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2025-01-20T11:22:33+02:00
summary:
gh-71339: Use new assertion methods in test_traceback (GH-128848)
files:
M Lib/test/test_traceback.py
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py
index abdfc4638f2e9c..a27a71c32ea521 100644
--- a/Lib/test/test_traceback.py
+++ b/Lib/test/test_traceback.py
@@ -86,7 +86,7 @@ def test_caret(self):
err = self.get_exception_format(self.syntax_error_with_caret,
SyntaxError)
self.assertEqual(len(err), 4)
- self.assertTrue(err[1].strip() == "return x!")
+ self.assertEqual(err[1].strip(), "return x!")
self.assertIn("^", err[2]) # third line has caret
self.assertEqual(err[1].find("!"), err[2].find("^")) # in the right place
self.assertEqual(err[2].count("^"), 1)
@@ -419,16 +419,10 @@ def do_test(firstlines, message, charset, lineno):
err_line = "raise RuntimeError('{0}')".format(message_ascii)
err_msg = "RuntimeError: {0}".format(message_ascii)
- self.assertIn(("line %s" % lineno), stdout[1],
- "Invalid line number: {0!r} instead of {1}".format(
- stdout[1], lineno))
- self.assertTrue(stdout[2].endswith(err_line),
- "Invalid traceback line: {0!r} instead of {1!r}".format(
- stdout[2], err_line))
+ self.assertIn("line %s" % lineno, stdout[1])
+ self.assertEndsWith(stdout[2], err_line)
actual_err_msg = stdout[3]
- self.assertTrue(actual_err_msg == err_msg,
- "Invalid error message: {0!r} instead of {1!r}".format(
- actual_err_msg, err_msg))
+ self.assertEqual(actual_err_msg, err_msg)
do_test("", "foo", "ascii", 3)
for charset in ("ascii", "iso-8859-1", "utf-8", "GBK"):
@@ -1809,9 +1803,9 @@ def check_traceback_format(self, cleanup_func=None):
banner = tb_lines[0]
self.assertEqual(len(tb_lines), 5)
location, source_line = tb_lines[-2], tb_lines[-1]
- self.assertTrue(banner.startswith('Traceback'))
- self.assertTrue(location.startswith(' File'))
- self.assertTrue(source_line.startswith(' raise'))
+ self.assertStartsWith(banner, 'Traceback')
+ self.assertStartsWith(location, ' File')
+ self.assertStartsWith(source_line, ' raise')
def test_traceback_format(self):
self.check_traceback_format()
@@ -2190,12 +2184,12 @@ def zero_div(self):
def check_zero_div(self, msg):
lines = msg.splitlines()
if has_no_debug_ranges():
- self.assertTrue(lines[-3].startswith(' File'))
+ self.assertStartsWith(lines[-3], ' File')
self.assertIn('1/0 # In zero_div', lines[-2])
else:
- self.assertTrue(lines[-4].startswith(' File'))
+ self.assertStartsWith(lines[-4], ' File')
self.assertIn('1/0 # In zero_div', lines[-3])
- self.assertTrue(lines[-1].startswith('ZeroDivisionError'), lines[-1])
+ self.assertStartsWith(lines[-1], 'ZeroDivisionError')
def test_simple(self):
try:
@@ -2205,12 +2199,12 @@ def test_simple(self):
lines = self.get_report(e).splitlines()
if has_no_debug_ranges():
self.assertEqual(len(lines), 4)
- self.assertTrue(lines[3].startswith('ZeroDivisionError'))
+ self.assertStartsWith(lines[3], 'ZeroDivisionError')
else:
self.assertEqual(len(lines), 5)
- self.assertTrue(lines[4].startswith('ZeroDivisionError'))
- self.assertTrue(lines[0].startswith('Traceback'))
- self.assertTrue(lines[1].startswith(' File'))
+ self.assertStartsWith(lines[4], 'ZeroDivisionError')
+ self.assertStartsWith(lines[0], 'Traceback')
+ self.assertStartsWith(lines[1], ' File')
self.assertIn('1/0 # Marker', lines[2])
def test_cause(self):
@@ -2251,9 +2245,9 @@ def test_context_suppression(self):
e = _
lines = self.get_report(e).splitlines()
self.assertEqual(len(lines), 4)
- self.assertTrue(lines[3].startswith('ZeroDivisionError'))
- self.assertTrue(lines[0].startswith('Traceback'))
- self.assertTrue(lines[1].startswith(' File'))
+ self.assertStartsWith(lines[3], 'ZeroDivisionError')
+ self.assertStartsWith(lines[0], 'Traceback')
+ self.assertStartsWith(lines[1], ' File')
self.assertIn('ZeroDivisionError from None', lines[2])
def test_cause_and_context(self):
1
0
gh-71339: Use assertIsSubclass() and assertNotIsSubclass() in test_decimal (GH-128827)
by serhiy-storchaka Jan. 20, 2025
by serhiy-storchaka Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/485d2e831ebf71a34634319adeeabdd1f9…
commit: 485d2e831ebf71a34634319adeeabdd1f9158bbe
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2025-01-20T11:20:49+02:00
summary:
gh-71339: Use assertIsSubclass() and assertNotIsSubclass() in test_decimal (GH-128827)
files:
M Lib/test/test_decimal.py
diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
index bc6c6427740949..02d3fa985e75b9 100644
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -752,7 +752,7 @@ def test_explicit_context_create_decimal(self):
for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
2**31-1, 2**31, 2**63-1, 2**63]:
d = nc.create_decimal(v)
- self.assertTrue(isinstance(d, Decimal))
+ self.assertIsInstance(d, Decimal)
self.assertEqual(int(d), v)
nc.prec = 3
@@ -2590,8 +2590,8 @@ class PythonAPItests:
def test_abc(self):
Decimal = self.decimal.Decimal
- self.assertTrue(issubclass(Decimal, numbers.Number))
- self.assertFalse(issubclass(Decimal, numbers.Real))
+ self.assertIsSubclass(Decimal, numbers.Number)
+ self.assertNotIsSubclass(Decimal, numbers.Real)
self.assertIsInstance(Decimal(0), numbers.Number)
self.assertNotIsInstance(Decimal(0), numbers.Real)
@@ -2690,7 +2690,7 @@ class MyDecimal(Decimal):
def __init__(self, _):
self.x = 'y'
- self.assertTrue(issubclass(MyDecimal, Decimal))
+ self.assertIsSubclass(MyDecimal, Decimal)
r = MyDecimal.from_float(0.1)
self.assertEqual(type(r), MyDecimal)
@@ -2908,31 +2908,31 @@ def test_exception_hierarchy(self):
Rounded = decimal.Rounded
Clamped = decimal.Clamped
- self.assertTrue(issubclass(DecimalException, ArithmeticError))
-
- self.assertTrue(issubclass(InvalidOperation, DecimalException))
- self.assertTrue(issubclass(FloatOperation, DecimalException))
- self.assertTrue(issubclass(FloatOperation, TypeError))
- self.assertTrue(issubclass(DivisionByZero, DecimalException))
- self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
- self.assertTrue(issubclass(Overflow, Rounded))
- self.assertTrue(issubclass(Overflow, Inexact))
- self.assertTrue(issubclass(Overflow, DecimalException))
- self.assertTrue(issubclass(Underflow, Inexact))
- self.assertTrue(issubclass(Underflow, Rounded))
- self.assertTrue(issubclass(Underflow, Subnormal))
- self.assertTrue(issubclass(Underflow, DecimalException))
-
- self.assertTrue(issubclass(Subnormal, DecimalException))
- self.assertTrue(issubclass(Inexact, DecimalException))
- self.assertTrue(issubclass(Rounded, DecimalException))
- self.assertTrue(issubclass(Clamped, DecimalException))
-
- self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
- self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
- self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
- self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
- self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
+ self.assertIsSubclass(DecimalException, ArithmeticError)
+
+ self.assertIsSubclass(InvalidOperation, DecimalException)
+ self.assertIsSubclass(FloatOperation, DecimalException)
+ self.assertIsSubclass(FloatOperation, TypeError)
+ self.assertIsSubclass(DivisionByZero, DecimalException)
+ self.assertIsSubclass(DivisionByZero, ZeroDivisionError)
+ self.assertIsSubclass(Overflow, Rounded)
+ self.assertIsSubclass(Overflow, Inexact)
+ self.assertIsSubclass(Overflow, DecimalException)
+ self.assertIsSubclass(Underflow, Inexact)
+ self.assertIsSubclass(Underflow, Rounded)
+ self.assertIsSubclass(Underflow, Subnormal)
+ self.assertIsSubclass(Underflow, DecimalException)
+
+ self.assertIsSubclass(Subnormal, DecimalException)
+ self.assertIsSubclass(Inexact, DecimalException)
+ self.assertIsSubclass(Rounded, DecimalException)
+ self.assertIsSubclass(Clamped, DecimalException)
+
+ self.assertIsSubclass(decimal.ConversionSyntax, InvalidOperation)
+ self.assertIsSubclass(decimal.DivisionImpossible, InvalidOperation)
+ self.assertIsSubclass(decimal.DivisionUndefined, InvalidOperation)
+ self.assertIsSubclass(decimal.DivisionUndefined, ZeroDivisionError)
+ self.assertIsSubclass(decimal.InvalidContext, InvalidOperation)
@requires_cdecimal
class CPythonAPItests(PythonAPItests, unittest.TestCase):
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/36aaf4137d55df3e324d98ec06b983b028…
commit: 36aaf4137d55df3e324d98ec06b983b0287d8949
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2025-01-20T11:19:43+02:00
summary:
gh-71339: Use new assertion methods in test_abc (GH-128826)
files:
M Lib/test/test_abc.py
diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py
index 5ce57cc209ea85..e90a8dc617c094 100644
--- a/Lib/test/test_abc.py
+++ b/Lib/test/test_abc.py
@@ -20,7 +20,7 @@ def test_abstractproperty_basics(self):
def foo(self): pass
self.assertTrue(foo.__isabstractmethod__)
def bar(self): pass
- self.assertFalse(hasattr(bar, "__isabstractmethod__"))
+ self.assertNotHasAttr(bar, "__isabstractmethod__")
class C(metaclass=abc_ABCMeta):
@abc.abstractproperty
@@ -89,7 +89,7 @@ def test_abstractmethod_basics(self):
def foo(self): pass
self.assertTrue(foo.__isabstractmethod__)
def bar(self): pass
- self.assertFalse(hasattr(bar, "__isabstractmethod__"))
+ self.assertNotHasAttr(bar, "__isabstractmethod__")
def test_abstractproperty_basics(self):
@property
@@ -276,21 +276,21 @@ class A(metaclass=abc_ABCMeta):
class B(object):
pass
b = B()
- self.assertFalse(issubclass(B, A))
- self.assertFalse(issubclass(B, (A,)))
+ self.assertNotIsSubclass(B, A)
+ self.assertNotIsSubclass(B, (A,))
self.assertNotIsInstance(b, A)
self.assertNotIsInstance(b, (A,))
B1 = A.register(B)
- self.assertTrue(issubclass(B, A))
- self.assertTrue(issubclass(B, (A,)))
+ self.assertIsSubclass(B, A)
+ self.assertIsSubclass(B, (A,))
self.assertIsInstance(b, A)
self.assertIsInstance(b, (A,))
self.assertIs(B1, B)
class C(B):
pass
c = C()
- self.assertTrue(issubclass(C, A))
- self.assertTrue(issubclass(C, (A,)))
+ self.assertIsSubclass(C, A)
+ self.assertIsSubclass(C, (A,))
self.assertIsInstance(c, A)
self.assertIsInstance(c, (A,))
@@ -301,16 +301,16 @@ class A(metaclass=abc_ABCMeta):
class B(object):
pass
b = B()
- self.assertTrue(issubclass(B, A))
- self.assertTrue(issubclass(B, (A,)))
+ self.assertIsSubclass(B, A)
+ self.assertIsSubclass(B, (A,))
self.assertIsInstance(b, A)
self.assertIsInstance(b, (A,))
@A.register
class C(B):
pass
c = C()
- self.assertTrue(issubclass(C, A))
- self.assertTrue(issubclass(C, (A,)))
+ self.assertIsSubclass(C, A)
+ self.assertIsSubclass(C, (A,))
self.assertIsInstance(c, A)
self.assertIsInstance(c, (A,))
self.assertIs(C, A.register(C))
@@ -321,14 +321,14 @@ class A(metaclass=abc_ABCMeta):
class B:
pass
b = B()
- self.assertFalse(isinstance(b, A))
- self.assertFalse(isinstance(b, (A,)))
+ self.assertNotIsInstance(b, A)
+ self.assertNotIsInstance(b, (A,))
token_old = abc_get_cache_token()
A.register(B)
token_new = abc_get_cache_token()
self.assertGreater(token_new, token_old)
- self.assertTrue(isinstance(b, A))
- self.assertTrue(isinstance(b, (A,)))
+ self.assertIsInstance(b, A)
+ self.assertIsInstance(b, (A,))
def test_registration_builtins(self):
class A(metaclass=abc_ABCMeta):
@@ -336,18 +336,18 @@ class A(metaclass=abc_ABCMeta):
A.register(int)
self.assertIsInstance(42, A)
self.assertIsInstance(42, (A,))
- self.assertTrue(issubclass(int, A))
- self.assertTrue(issubclass(int, (A,)))
+ self.assertIsSubclass(int, A)
+ self.assertIsSubclass(int, (A,))
class B(A):
pass
B.register(str)
class C(str): pass
self.assertIsInstance("", A)
self.assertIsInstance("", (A,))
- self.assertTrue(issubclass(str, A))
- self.assertTrue(issubclass(str, (A,)))
- self.assertTrue(issubclass(C, A))
- self.assertTrue(issubclass(C, (A,)))
+ self.assertIsSubclass(str, A)
+ self.assertIsSubclass(str, (A,))
+ self.assertIsSubclass(C, A)
+ self.assertIsSubclass(C, (A,))
def test_registration_edge_cases(self):
class A(metaclass=abc_ABCMeta):
@@ -375,39 +375,39 @@ class A(metaclass=abc_ABCMeta):
def test_registration_transitiveness(self):
class A(metaclass=abc_ABCMeta):
pass
- self.assertTrue(issubclass(A, A))
- self.assertTrue(issubclass(A, (A,)))
+ self.assertIsSubclass(A, A)
+ self.assertIsSubclass(A, (A,))
class B(metaclass=abc_ABCMeta):
pass
- self.assertFalse(issubclass(A, B))
- self.assertFalse(issubclass(A, (B,)))
- self.assertFalse(issubclass(B, A))
- self.assertFalse(issubclass(B, (A,)))
+ self.assertNotIsSubclass(A, B)
+ self.assertNotIsSubclass(A, (B,))
+ self.assertNotIsSubclass(B, A)
+ self.assertNotIsSubclass(B, (A,))
class C(metaclass=abc_ABCMeta):
pass
A.register(B)
class B1(B):
pass
- self.assertTrue(issubclass(B1, A))
- self.assertTrue(issubclass(B1, (A,)))
+ self.assertIsSubclass(B1, A)
+ self.assertIsSubclass(B1, (A,))
class C1(C):
pass
B1.register(C1)
- self.assertFalse(issubclass(C, B))
- self.assertFalse(issubclass(C, (B,)))
- self.assertFalse(issubclass(C, B1))
- self.assertFalse(issubclass(C, (B1,)))
- self.assertTrue(issubclass(C1, A))
- self.assertTrue(issubclass(C1, (A,)))
- self.assertTrue(issubclass(C1, B))
- self.assertTrue(issubclass(C1, (B,)))
- self.assertTrue(issubclass(C1, B1))
- self.assertTrue(issubclass(C1, (B1,)))
+ self.assertNotIsSubclass(C, B)
+ self.assertNotIsSubclass(C, (B,))
+ self.assertNotIsSubclass(C, B1)
+ self.assertNotIsSubclass(C, (B1,))
+ self.assertIsSubclass(C1, A)
+ self.assertIsSubclass(C1, (A,))
+ self.assertIsSubclass(C1, B)
+ self.assertIsSubclass(C1, (B,))
+ self.assertIsSubclass(C1, B1)
+ self.assertIsSubclass(C1, (B1,))
C1.register(int)
class MyInt(int):
pass
- self.assertTrue(issubclass(MyInt, A))
- self.assertTrue(issubclass(MyInt, (A,)))
+ self.assertIsSubclass(MyInt, A)
+ self.assertIsSubclass(MyInt, (A,))
self.assertIsInstance(42, A)
self.assertIsInstance(42, (A,))
@@ -467,16 +467,16 @@ def __subclasshook__(cls, C):
if cls is A:
return 'foo' in C.__dict__
return NotImplemented
- self.assertFalse(issubclass(A, A))
- self.assertFalse(issubclass(A, (A,)))
+ self.assertNotIsSubclass(A, A)
+ self.assertNotIsSubclass(A, (A,))
class B:
foo = 42
- self.assertTrue(issubclass(B, A))
- self.assertTrue(issubclass(B, (A,)))
+ self.assertIsSubclass(B, A)
+ self.assertIsSubclass(B, (A,))
class C:
spam = 42
- self.assertFalse(issubclass(C, A))
- self.assertFalse(issubclass(C, (A,)))
+ self.assertNotIsSubclass(C, A)
+ self.assertNotIsSubclass(C, (A,))
def test_all_new_methods_are_called(self):
class A(metaclass=abc_ABCMeta):
@@ -493,7 +493,7 @@ class C(A, B):
self.assertEqual(B.counter, 1)
def test_ABC_has___slots__(self):
- self.assertTrue(hasattr(abc.ABC, '__slots__'))
+ self.assertHasAttr(abc.ABC, '__slots__')
def test_tricky_new_works(self):
def with_metaclass(meta, *bases):
@@ -515,7 +515,7 @@ def foo(self):
del A.foo
self.assertEqual(A.__abstractmethods__, {'foo'})
- self.assertFalse(hasattr(A, 'foo'))
+ self.assertNotHasAttr(A, 'foo')
abc.update_abstractmethods(A)
@@ -588,7 +588,7 @@ def updated_foo(self):
A.foo = updated_foo
abc.update_abstractmethods(A)
A()
- self.assertFalse(hasattr(A, '__abstractmethods__'))
+ self.assertNotHasAttr(A, '__abstractmethods__')
def test_update_del_implementation(self):
class A(metaclass=abc_ABCMeta):
1
0
[3.13] gh-71339: Add additional assertion methods in test.support (GH-128707) (GH-128815)
by serhiy-storchaka Jan. 20, 2025
by serhiy-storchaka Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/c6a566e47b9903d48e6e1e78a1af20e6c6…
commit: c6a566e47b9903d48e6e1e78a1af20e6c6c535cf
branch: 3.13
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2025-01-20T11:19:00+02:00
summary:
[3.13] gh-71339: Add additional assertion methods in test.support (GH-128707) (GH-128815)
Add a mix-in class ExtraAssertions containing the following methods:
* assertHasAttr() and assertNotHasAttr()
* assertIsSubclass() and assertNotIsSubclass()
* assertStartsWith() and assertNotStartsWith()
* assertEndsWith() and assertNotEndsWith()
(cherry picked from commit 06cad77a5b345adde88609be9c3c470c5cd9f417)
files:
M Lib/test/support/testcase.py
M Lib/test/test_descr.py
M Lib/test/test_gdb/util.py
M Lib/test/test_importlib/resources/test_functional.py
M Lib/test/test_pyclbr.py
M Lib/test/test_typing.py
M Lib/test/test_venv.py
diff --git a/Lib/test/support/testcase.py b/Lib/test/support/testcase.py
index fad1e4cb3499c0..fd32457d1467ca 100644
--- a/Lib/test/support/testcase.py
+++ b/Lib/test/support/testcase.py
@@ -1,6 +1,63 @@
from math import copysign, isnan
+class ExtraAssertions:
+
+ def assertIsSubclass(self, cls, superclass, msg=None):
+ if issubclass(cls, superclass):
+ return
+ standardMsg = f'{cls!r} is not a subclass of {superclass!r}'
+ self.fail(self._formatMessage(msg, standardMsg))
+
+ def assertNotIsSubclass(self, cls, superclass, msg=None):
+ if not issubclass(cls, superclass):
+ return
+ standardMsg = f'{cls!r} is a subclass of {superclass!r}'
+ self.fail(self._formatMessage(msg, standardMsg))
+
+ def assertHasAttr(self, obj, name, msg=None):
+ if not hasattr(obj, name):
+ if isinstance(obj, types.ModuleType):
+ standardMsg = f'module {obj.__name__!r} has no attribute {name!r}'
+ elif isinstance(obj, type):
+ standardMsg = f'type object {obj.__name__!r} has no attribute {name!r}'
+ else:
+ standardMsg = f'{type(obj).__name__!r} object has no attribute {name!r}'
+ self.fail(self._formatMessage(msg, standardMsg))
+
+ def assertNotHasAttr(self, obj, name, msg=None):
+ if hasattr(obj, name):
+ if isinstance(obj, types.ModuleType):
+ standardMsg = f'module {obj.__name__!r} has unexpected attribute {name!r}'
+ elif isinstance(obj, type):
+ standardMsg = f'type object {obj.__name__!r} has unexpected attribute {name!r}'
+ else:
+ standardMsg = f'{type(obj).__name__!r} object has unexpected attribute {name!r}'
+ self.fail(self._formatMessage(msg, standardMsg))
+
+ def assertStartsWith(self, s, prefix, msg=None):
+ if s.startswith(prefix):
+ return
+ standardMsg = f"{s!r} doesn't start with {prefix!r}"
+ self.fail(self._formatMessage(msg, standardMsg))
+
+ def assertNotStartsWith(self, s, prefix, msg=None):
+ if not s.startswith(prefix):
+ return
+ self.fail(self._formatMessage(msg, f"{s!r} starts with {prefix!r}"))
+
+ def assertEndsWith(self, s, suffix, msg=None):
+ if s.endswith(suffix):
+ return
+ standardMsg = f"{s!r} doesn't end with {suffix!r}"
+ self.fail(self._formatMessage(msg, standardMsg))
+
+ def assertNotEndsWith(self, s, suffix, msg=None):
+ if not s.endswith(suffix):
+ return
+ self.fail(self._formatMessage(msg, f"{s!r} ends with {suffix!r}"))
+
+
class ExceptionIsLikeMixin:
def assertExceptionIsLike(self, exc, template):
"""
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 14bd87eb9c8d84..dd1fa321ecf171 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -15,6 +15,7 @@
from copy import deepcopy
from contextlib import redirect_stdout
from test import support
+from test.support.testcase import ExtraAssertions
try:
import _testcapi
@@ -403,15 +404,7 @@ def test_wrap_lenfunc_bad_cast(self):
self.assertEqual(range(sys.maxsize).__len__(), sys.maxsize)
-class ClassPropertiesAndMethods(unittest.TestCase):
-
- def assertHasAttr(self, obj, name):
- self.assertTrue(hasattr(obj, name),
- '%r has no attribute %r' % (obj, name))
-
- def assertNotHasAttr(self, obj, name):
- self.assertFalse(hasattr(obj, name),
- '%r has unexpected attribute %r' % (obj, name))
+class ClassPropertiesAndMethods(unittest.TestCase, ExtraAssertions):
def test_python_dicts(self):
# Testing Python subclass of dict...
diff --git a/Lib/test/test_gdb/util.py b/Lib/test/test_gdb/util.py
index 8fe9cfc543395e..54c6b2de7cc99d 100644
--- a/Lib/test/test_gdb/util.py
+++ b/Lib/test/test_gdb/util.py
@@ -7,6 +7,7 @@
import sysconfig
import unittest
from test import support
+from test.support.testcase import ExtraAssertions
GDB_PROGRAM = shutil.which('gdb') or 'gdb'
@@ -152,7 +153,7 @@ def setup_module():
print()
-class DebuggerTests(unittest.TestCase):
+class DebuggerTests(unittest.TestCase, ExtraAssertions):
"""Test that the debugger can debug Python."""
@@ -280,11 +281,6 @@ def get_stack_trace(self, source=None, script=None,
return out
- def assertEndsWith(self, actual, exp_end):
- '''Ensure that the given "actual" string ends with "exp_end"'''
- self.assertTrue(actual.endswith(exp_end),
- msg='%r did not end with %r' % (actual, exp_end))
-
def assertMultilineMatches(self, actual, pattern):
m = re.match(pattern, actual, re.DOTALL)
if not m:
diff --git a/Lib/test/test_importlib/resources/test_functional.py b/Lib/test/test_importlib/resources/test_functional.py
index 4317abf3162c52..3fc1ade35bef5a 100644
--- a/Lib/test/test_importlib/resources/test_functional.py
+++ b/Lib/test/test_importlib/resources/test_functional.py
@@ -3,6 +3,7 @@
import importlib
from test.support import warnings_helper
+from test.support.testcase import ExtraAssertions
from importlib import resources
@@ -28,7 +29,7 @@ def anchor02(self):
return importlib.import_module('data02')
-class FunctionalAPIBase(util.DiskSetup):
+class FunctionalAPIBase(util.DiskSetup, ExtraAssertions):
def setUp(self):
super().setUp()
self.load_fixture('data02')
@@ -43,12 +44,6 @@ def _gen_resourcetxt_path_parts(self):
with self.subTest(path_parts=path_parts):
yield path_parts
- def assertEndsWith(self, string, suffix):
- """Assert that `string` ends with `suffix`.
-
- Used to ignore an architecture-specific UTF-16 byte-order mark."""
- self.assertEqual(string[-len(suffix) :], suffix)
-
def test_read_text(self):
self.assertEqual(
resources.read_text(self.anchor01, 'utf-8.file'),
diff --git a/Lib/test/test_pyclbr.py b/Lib/test/test_pyclbr.py
index d409a2d4a312e6..a65705aaf53abc 100644
--- a/Lib/test/test_pyclbr.py
+++ b/Lib/test/test_pyclbr.py
@@ -10,6 +10,7 @@
from unittest import TestCase, main as unittest_main
from test.test_importlib import util as test_importlib_util
import warnings
+from test.support.testcase import ExtraAssertions
StaticMethodType = type(staticmethod(lambda: None))
@@ -22,7 +23,7 @@
# is imperfect (as designed), testModule is called with a set of
# members to ignore.
-class PyclbrTest(TestCase):
+class PyclbrTest(TestCase, ExtraAssertions):
def assertListEq(self, l1, l2, ignore):
''' succeed iff {l1} - {ignore} == {l2} - {ignore} '''
@@ -31,14 +32,6 @@ def assertListEq(self, l1, l2, ignore):
print("l1=%r\nl2=%r\nignore=%r" % (l1, l2, ignore), file=sys.stderr)
self.fail("%r missing" % missing.pop())
- def assertHasattr(self, obj, attr, ignore):
- ''' succeed iff hasattr(obj,attr) or attr in ignore. '''
- if attr in ignore: return
- if not hasattr(obj, attr): print("???", attr)
- self.assertTrue(hasattr(obj, attr),
- 'expected hasattr(%r, %r)' % (obj, attr))
-
-
def assertHaskey(self, obj, key, ignore):
''' succeed iff key in obj or key in ignore. '''
if key in ignore: return
@@ -86,7 +79,7 @@ def ismethod(oclass, obj, name):
for name, value in dict.items():
if name in ignore:
continue
- self.assertHasattr(module, name, ignore)
+ self.assertHasAttr(module, name, ignore)
py_item = getattr(module, name)
if isinstance(value, pyclbr.Function):
self.assertIsInstance(py_item, (FunctionType, BuiltinFunctionType))
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 140ceb74735570..89a32c7a1a0d14 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -46,6 +46,7 @@
import types
from test.support import captured_stderr, cpython_only, infinite_recursion, requires_docstrings, import_helper
+from test.support.testcase import ExtraAssertions
from test.typinganndata import ann_module695, mod_generics_cache, _typed_dict_helper
@@ -54,21 +55,7 @@
CANNOT_SUBCLASS_INSTANCE = 'Cannot subclass an instance of %s'
-class BaseTestCase(TestCase):
-
- def assertIsSubclass(self, cls, class_or_tuple, msg=None):
- if not issubclass(cls, class_or_tuple):
- message = '%r is not a subclass of %r' % (cls, class_or_tuple)
- if msg is not None:
- message += ' : %s' % msg
- raise self.failureException(message)
-
- def assertNotIsSubclass(self, cls, class_or_tuple, msg=None):
- if issubclass(cls, class_or_tuple):
- message = '%r is a subclass of %r' % (cls, class_or_tuple)
- if msg is not None:
- message += ' : %s' % msg
- raise self.failureException(message)
+class BaseTestCase(TestCase, ExtraAssertions):
def clear_caches(self):
for f in typing._cleanups:
@@ -1249,10 +1236,6 @@ class Gen[*Ts]: ...
class TypeVarTupleTests(BaseTestCase):
- def assertEndsWith(self, string, tail):
- if not string.endswith(tail):
- self.fail(f"String {string!r} does not end with {tail!r}")
-
def test_name(self):
Ts = TypeVarTuple('Ts')
self.assertEqual(Ts.__name__, 'Ts')
diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py
index 0b09010c69d4ea..c39c83f9d0a5c3 100644
--- a/Lib/test/test_venv.py
+++ b/Lib/test/test_venv.py
@@ -26,6 +26,7 @@
requires_resource, copy_python_src_ignore)
from test.support.os_helper import (can_symlink, EnvironmentVarGuard, rmtree,
TESTFN, FakePath)
+from test.support.testcase import ExtraAssertions
import unittest
import venv
from unittest.mock import patch, Mock
@@ -64,7 +65,7 @@ def check_output(cmd, encoding=None):
)
return out, err
-class BaseTest(unittest.TestCase):
+class BaseTest(unittest.TestCase, ExtraAssertions):
"""Base class for venv tests."""
maxDiff = 80 * 50
@@ -111,10 +112,6 @@ def get_text_file_contents(self, *args, encoding='utf-8'):
result = f.read()
return result
- def assertEndsWith(self, string, tail):
- if not string.endswith(tail):
- self.fail(f"String {string!r} does not end with {tail!r}")
-
class BasicTest(BaseTest):
"""Test venv module functionality."""
1
0
gh-71339: Improve error report for types in assertHasAttr() and assertNotHasAttr() (GH-128818)
by serhiy-storchaka Jan. 20, 2025
by serhiy-storchaka Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/da122b5facbbae9197a108e0a3c4b3f059…
commit: da122b5facbbae9197a108e0a3c4b3f0594c5e92
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2025-01-20T11:17:49+02:00
summary:
gh-71339: Improve error report for types in assertHasAttr() and assertNotHasAttr() (GH-128818)
files:
M Lib/test/test_unittest/test_case.py
M Lib/unittest/case.py
diff --git a/Lib/test/test_unittest/test_case.py b/Lib/test/test_unittest/test_case.py
index cd366496eedca3..df1381451b7ebc 100644
--- a/Lib/test/test_unittest/test_case.py
+++ b/Lib/test/test_unittest/test_case.py
@@ -795,7 +795,15 @@ def testAssertHasAttr(self):
with self.assertRaises(self.failureException) as cm:
self.assertHasAttr(a, 'y')
self.assertEqual(str(cm.exception),
- "List instance has no attribute 'y'")
+ "'List' object has no attribute 'y'")
+ with self.assertRaises(self.failureException) as cm:
+ self.assertHasAttr(List, 'spam')
+ self.assertEqual(str(cm.exception),
+ "type object 'List' has no attribute 'spam'")
+ with self.assertRaises(self.failureException) as cm:
+ self.assertHasAttr(sys, 'spam')
+ self.assertEqual(str(cm.exception),
+ "module 'sys' has no attribute 'spam'")
with self.assertRaises(self.failureException) as cm:
self.assertHasAttr(a, 'y', 'ababahalamaha')
@@ -811,7 +819,15 @@ def testAssertNotHasAttr(self):
with self.assertRaises(self.failureException) as cm:
self.assertNotHasAttr(a, 'x')
self.assertEqual(str(cm.exception),
- "List instance has unexpected attribute 'x'")
+ "'List' object has unexpected attribute 'x'")
+ with self.assertRaises(self.failureException) as cm:
+ self.assertNotHasAttr(List, 'append')
+ self.assertEqual(str(cm.exception),
+ "type object 'List' has unexpected attribute 'append'")
+ with self.assertRaises(self.failureException) as cm:
+ self.assertNotHasAttr(sys, 'modules')
+ self.assertEqual(str(cm.exception),
+ "module 'sys' has unexpected attribute 'modules'")
with self.assertRaises(self.failureException) as cm:
self.assertNotHasAttr(a, 'x', 'ababahalamaha')
diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py
index e9ef551d0b3ded..10c3b7e122371e 100644
--- a/Lib/unittest/case.py
+++ b/Lib/unittest/case.py
@@ -1372,16 +1372,20 @@ def assertHasAttr(self, obj, name, msg=None):
if not hasattr(obj, name):
if isinstance(obj, types.ModuleType):
standardMsg = f'module {obj.__name__!r} has no attribute {name!r}'
+ elif isinstance(obj, type):
+ standardMsg = f'type object {obj.__name__!r} has no attribute {name!r}'
else:
- standardMsg = f'{type(obj).__name__} instance has no attribute {name!r}'
+ standardMsg = f'{type(obj).__name__!r} object has no attribute {name!r}'
self.fail(self._formatMessage(msg, standardMsg))
def assertNotHasAttr(self, obj, name, msg=None):
if hasattr(obj, name):
if isinstance(obj, types.ModuleType):
standardMsg = f'module {obj.__name__!r} has unexpected attribute {name!r}'
+ elif isinstance(obj, type):
+ standardMsg = f'type object {obj.__name__!r} has unexpected attribute {name!r}'
else:
- standardMsg = f'{type(obj).__name__} instance has unexpected attribute {name!r}'
+ standardMsg = f'{type(obj).__name__!r} object has unexpected attribute {name!r}'
self.fail(self._formatMessage(msg, standardMsg))
def assertRaisesRegex(self, expected_exception, expected_regex,
1
0