python-peps/pep-0741/index.html

1157 lines
94 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 741 Python Configuration C API | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0741/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 741 Python Configuration C API | peps.python.org'>
<meta property="og:description" content="Add a C API to configure the Python initialization without relying on C structures and the ability to make ABI-compatible changes in the future.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0741/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Add a C API to configure the Python initialization without relying on C structures and the ability to make ABI-compatible changes in the future.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 741</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 741 Python Configuration C API</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Victor Stinner &lt;vstinner&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Discussions-To<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="https://discuss.python.org/t/pep-741-python-configuration-c-api-second-version/45403">Discourse thread</a></dd>
<dt class="field-odd">Status<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-even">Type<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-odd">Created<span class="colon">:</span></dt>
<dd class="field-odd">18-Jan-2024</dd>
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
<dd class="field-even">3.14</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="https://discuss.python.org/t/pep-741-python-configuration-c-api/43637" title="Discourse thread">19-Jan-2024</a>,
<a class="reference external" href="https://discuss.python.org/t/pep-741-python-configuration-c-api-second-version/45403" title="Discourse thread">08-Feb-2024</a></dd>
<dt class="field-even">Resolution<span class="colon">:</span></dt>
<dd class="field-even"><a class="reference external" href="https://discuss.python.org/t/pep-741-python-configuration-c-api-second-version/45403/88">Discourse message</a></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
<li><a class="reference internal" href="#get-the-runtime-configuration">Get the runtime configuration</a></li>
<li><a class="reference internal" href="#security-fix">Security fix</a></li>
<li><a class="reference internal" href="#redundancy-between-pypreconfig-and-pyconfig">Redundancy between PyPreConfig and PyConfig</a></li>
<li><a class="reference internal" href="#embedding-python">Embedding Python</a><ul>
<li><a class="reference internal" href="#applications-embedding-python">Applications embedding Python</a></li>
<li><a class="reference internal" href="#libraries-embedding-python">Libraries embedding Python</a></li>
<li><a class="reference internal" href="#utilities-creating-standalone-applications">Utilities creating standalone applications</a></li>
</ul>
</li>
<li><a class="reference internal" href="#set-the-runtime-configuration">Set the runtime configuration</a></li>
</ul>
</li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#pyinitconfig-structure">PyInitConfig structure</a></li>
<li><a class="reference internal" href="#configuration-options">Configuration Options</a><ul>
<li><a class="reference internal" href="#public-configuration-options">Public configuration options</a></li>
<li><a class="reference internal" href="#read-only-configuration-options">Read-only configuration options</a></li>
</ul>
</li>
<li><a class="reference internal" href="#create-config">Create Config</a></li>
<li><a class="reference internal" href="#get-options">Get Options</a></li>
<li><a class="reference internal" href="#set-options">Set Options</a></li>
<li><a class="reference internal" href="#initialize-python">Initialize Python</a></li>
<li><a class="reference internal" href="#error-handling">Error Handling</a></li>
<li><a class="reference internal" href="#get-and-set-the-runtime-configuration">Get and Set the Runtime Configuration</a></li>
<li><a class="reference internal" href="#stability">Stability</a></li>
<li><a class="reference internal" href="#interaction-with-the-pypreconfig-and-pyconfig-apis">Interaction with the PyPreConfig and PyConfig APIs</a></li>
</ul>
</li>
<li><a class="reference internal" href="#examples">Examples</a><ul>
<li><a class="reference internal" href="#id1">Initialize Python</a></li>
<li><a class="reference internal" href="#increase-initialization-bytes-warning-option">Increase initialization bytes_warning option</a></li>
<li><a class="reference internal" href="#get-the-runtime-verbose-option">Get the runtime verbose option</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul>
<li><a class="reference internal" href="#configuration-as-text">Configuration as text</a></li>
<li><a class="reference internal" href="#refer-to-an-option-with-an-integer">Refer to an option with an integer</a></li>
<li><a class="reference internal" href="#multi-phase-initialization-similar-to-pep-432">Multi-phase initialization (similar to PEP 432)</a></li>
<li><a class="reference internal" href="#locale-encoding-and-wide-strings">Locale encoding and wide strings</a></li>
</ul>
</li>
<li><a class="reference internal" href="#discussions">Discussions</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>Add a C API to configure the Python initialization without relying on C
structures and the ability to make ABI-compatible changes in the future.</p>
<p>Complete <a class="pep reference internal" href="../pep-0587/" title="PEP 587 Python Initialization Configuration">PEP 587</a> API by adding <code class="docutils literal notranslate"><span class="pre">PyInitConfig_AddModule()</span></code> which can be
used to add a built-in extension module; feature previously referred to
as the “inittab”.</p>
<p>Add <code class="docutils literal notranslate"><span class="pre">PyConfig_Get()</span></code> and <code class="docutils literal notranslate"><span class="pre">PyConfig_Set()</span></code> functions to
get and set the current runtime configuration.</p>
<p><a class="pep reference internal" href="../pep-0587/" title="PEP 587 Python Initialization Configuration">PEP 587</a> “Python Initialization Configuration” unified all the ways to
configure the Python <strong>initialization</strong>. This PEP unifies also the
configuration of the Python <strong>preinitialization</strong> and the Python
<strong>initialization</strong> in a single API. Moreover, this PEP only provides a
single choice to embed Python, instead of having two “Python” and
“Isolated” choices (<a class="pep reference internal" href="../pep-0587/" title="PEP 587 Python Initialization Configuration">PEP 587</a>), to simplify the API further.</p>
<p>The lower level <a class="pep reference internal" href="../pep-0587/" title="PEP 587 Python Initialization Configuration">PEP 587</a> <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code> API remains available for use
cases with an intentionally higher level of coupling to CPython
implementation details (such as emulating the full functionality of
CPythons CLI, including its configuration mechanisms).</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<section id="get-the-runtime-configuration">
<h3><a class="toc-backref" href="#get-the-runtime-configuration" role="doc-backlink">Get the runtime configuration</a></h3>
<p><a class="pep reference internal" href="../pep-0587/" title="PEP 587 Python Initialization Configuration">PEP 587</a> has no API to <strong>get</strong> the <strong>current</strong> runtime configuration,
only to <strong>configure</strong> the Python <strong>initialization</strong>.</p>
<p>For example, the global configuration variable
<code class="docutils literal notranslate"><span class="pre">Py_UnbufferedStdioFlag</span></code> was deprecated in Python 3.12 and using
<code class="docutils literal notranslate"><span class="pre">PyConfig.buffered_stdio</span></code> is recommended instead. It only works to
configure Python, there is no public API to get
<code class="docutils literal notranslate"><span class="pre">PyConfig.buffered_stdio</span></code>.</p>
<p>Users of the limited C API are asking for a public API to get the
current runtime configuration.</p>
<p>Cython needs to get the <code class="docutils literal notranslate"><span class="pre">optimization_level</span></code> configuration option:
<a class="reference external" href="https://github.com/python/cpython/issues/99872">issue</a>.</p>
<p>When global configuration variables were deprecated in 2022, <a class="reference external" href="https://github.com/python/cpython/issues/93103#issuecomment-1136462708">Marc-André
Lemburg requested</a>
a C API to access these configuration variables at runtime (not only
during Python initialization).</p>
</section>
<section id="security-fix">
<h3><a class="toc-backref" href="#security-fix" role="doc-backlink">Security fix</a></h3>
<p>To fix <a class="reference external" href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10735">CVE-2020-10735</a>,
a denial-of-service when converting a very large string to an integer (in base
10), it was discussed to add a new <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code> member to stable
branches which affects the ABI.</p>
<p>Gregory P. Smith proposed a different API using text based configuration
file to not be limited by <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code> members: <a class="reference external" href="https://discuss.python.org/t/fr-allow-private-runtime-config-to-enable-extending-without-breaking-the-pyconfig-abi/18004">FR: Allow private
runtime config to enable extending without breaking the PyConfig ABI</a>
(August 2022).</p>
<p>In the end, it was decided to not add a new <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code> member to
stable branches, but only add a new <code class="docutils literal notranslate"><span class="pre">PyConfig.int_max_str_digits</span></code>
member to the development branch (which became Python 3.12). A dedicated
private global variable (unrelated to <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code>) is used in stable
branches.</p>
</section>
<section id="redundancy-between-pypreconfig-and-pyconfig">
<h3><a class="toc-backref" href="#redundancy-between-pypreconfig-and-pyconfig" role="doc-backlink">Redundancy between PyPreConfig and PyConfig</a></h3>
<p>The Python preinitialization uses the <code class="docutils literal notranslate"><span class="pre">PyPreConfig</span></code> structure and the
Python initialization uses the <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code> structure. Both structures
have four duplicated members: <code class="docutils literal notranslate"><span class="pre">dev_mode</span></code>, <code class="docutils literal notranslate"><span class="pre">parse_argv</span></code>, <code class="docutils literal notranslate"><span class="pre">isolated</span></code>
and <code class="docutils literal notranslate"><span class="pre">use_environment</span></code>.</p>
<p>The redundancy is caused by the fact that the two structures are
separated, whereas some <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code> members are needed by the
preinitialization.</p>
</section>
<section id="embedding-python">
<h3><a class="toc-backref" href="#embedding-python" role="doc-backlink">Embedding Python</a></h3>
<section id="applications-embedding-python">
<h4><a class="toc-backref" href="#applications-embedding-python" role="doc-backlink">Applications embedding Python</a></h4>
<p>Examples:</p>
<ul class="simple">
<li><a class="reference external" href="https://www.blender.org/">Blender 3D graphics</a>.</li>
<li><a class="reference external" href="https://fontforge.org/">fontforge</a> font editor.</li>
<li><a class="reference external" href="https://www.gimp.org/">Gimp</a>.</li>
<li><a class="reference external" href="https://www.libreoffice.org/">LibreOffice</a>.</li>
<li><a class="reference external" href="https://obsproject.com/">OBS Studio</a>.</li>
<li><a class="reference external" href="https://www.mapeditor.org/">Tiled</a>.</li>
<li><a class="reference external" href="https://www.vim.org/">vim</a> text editor.</li>
</ul>
<p>On Linux, FreeBSD and macOS, applications are usually either statically
linked to a <code class="docutils literal notranslate"><span class="pre">libpython</span></code>, or load dynamically a <code class="docutils literal notranslate"><span class="pre">libpython</span></code> . The
<code class="docutils literal notranslate"><span class="pre">libpython</span></code> shared library is versioned, example:
<code class="docutils literal notranslate"><span class="pre">libpython3.12.so</span></code> for Python 3.12 on Linux.</p>
<p>The vim project can target the stable ABI. Usually, the “system Python”
version is used. Its not currently possible to select which Python
version to use. Users would like the ability to select a newer Python
on demand.</p>
<p>On Linux, another approach to deploy an application embedding Python,
such as GIMP, is to include Python in Flatpack, AppImage or Snap
“container”. In this case, the application brings its own copy of Python
version with the container.</p>
</section>
<section id="libraries-embedding-python">
<h4><a class="toc-backref" href="#libraries-embedding-python" role="doc-backlink">Libraries embedding Python</a></h4>
<p>Examples:</p>
<ul class="simple">
<li><a class="reference external" href="https://modwsgi.readthedocs.io/">Apache mod_wsgi</a>
(<a class="reference external" href="https://github.com/GrahamDumpleton/mod_wsgi/blob/f54eadd6da8e3da0faccd497d4165de435b97242/src/server/wsgi_interp.c#L2367-L2404">source</a>).</li>
<li><a class="reference external" href="https://github.com/yglukhov/nimpy">nimpy</a>:
Nim - Python bridge.</li>
<li><a class="reference external" href="https://github.com/PyO3/pyo3">PyO3</a>:
Rust bindings for the Python interpreter.</li>
</ul>
</section>
<section id="utilities-creating-standalone-applications">
<h4><a class="toc-backref" href="#utilities-creating-standalone-applications" role="doc-backlink">Utilities creating standalone applications</a></h4>
<ul class="simple">
<li><a class="reference external" href="https://py2app.readthedocs.io/">py2app</a> for macOS.</li>
<li><a class="reference external" href="http://www.py2exe.org/">py2exe</a> for Windows.</li>
<li><a class="reference external" href="https://pyinstaller.org/">pyinstaller</a>.</li>
<li><a class="reference external" href="https://github.com/indygreg/PyOxidizer">PyOxidizer</a>:
it uses the PEP 587 PyConfig API.</li>
</ul>
<p>These utilities create standalone applications, they are not linked to
libpython.</p>
</section>
</section>
<section id="set-the-runtime-configuration">
<h3><a class="toc-backref" href="#set-the-runtime-configuration" role="doc-backlink">Set the runtime configuration</a></h3>
<p><a class="reference external" href="https://discuss.python.org/t/fr-allow-private-runtime-config-to-enable-extending-without-breaking-the-pyconfig-abi/18004/34">Marc-André Lemburg requested</a>
a C API to <strong>set</strong> the value of some configuration options at runtime:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">optimization_level</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">verbose</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">parser_debug</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">inspect</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">write_bytecode</span></code></li>
</ul>
<p>Previously, it was possible to set directly global configuration
variables:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">Py_OptimizeFlag</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Py_VerboseFlag</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Py_DebugFlag</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Py_InspectFlag</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">Py_DontWriteBytecodeFlag</span></code></li>
</ul>
<p>But these configuration flags were deprecated in Python 3.12 and are
scheduled for removal in Python 3.14.</p>
</section>
</section>
<section id="specification">
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
<p>Add C API functions and structure to configure the Python
initialization:</p>
<ul class="simple">
<li>Create config:<ul>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig</span></code> opaque structure.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_Create()</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_Free(config)</span></code>.</li>
</ul>
</li>
<li>Get options:<ul>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_HasOption(config,</span> <span class="pre">name)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_GetInt(config,</span> <span class="pre">name,</span> <span class="pre">&amp;value)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_GetStr(config,</span> <span class="pre">name,</span> <span class="pre">&amp;value)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_GetStrList(config,</span> <span class="pre">name,</span> <span class="pre">&amp;length,</span> <span class="pre">&amp;items)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_FreeStrList()</span></code>.</li>
</ul>
</li>
<li>Set options:<ul>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_SetInt(config,</span> <span class="pre">name,</span> <span class="pre">value)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_SetStr(config,</span> <span class="pre">name,</span> <span class="pre">value)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_SetStrList(config,</span> <span class="pre">name,</span> <span class="pre">length,</span> <span class="pre">items)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_AddModule(config,</span> <span class="pre">name,</span> <span class="pre">initfunc)</span></code></li>
</ul>
</li>
<li>Initialize:<ul>
<li><code class="docutils literal notranslate"><span class="pre">Py_InitializeFromInitConfig(config)</span></code>.</li>
</ul>
</li>
<li>Error handling:<ul>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_GetError(config,</span> <span class="pre">&amp;err_msg)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyInitConfig_GetExitcode(config,</span> <span class="pre">&amp;exitcode)</span></code>.</li>
</ul>
</li>
</ul>
<p>Add C API functions to get and set the current runtime configuration:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">PyConfig_Get(name)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyConfig_GetInt(name,</span> <span class="pre">&amp;value)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyConfig_Set(name)</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyConfig_Names()</span></code>.</li>
</ul>
<p>The C API uses null-terminated UTF-8 encoded strings to refer to a
configuration option name.</p>
<p>These C API functions are excluded from the limited C API.</p>
<section id="pyinitconfig-structure">
<h3><a class="toc-backref" href="#pyinitconfig-structure" role="doc-backlink">PyInitConfig structure</a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">PyInitConfig</span></code> structure is implemented by combining the three
structures of the <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code> API and has an <code class="docutils literal notranslate"><span class="pre">inittab</span></code> member as
well:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">PyPreConfig</span> <span class="pre">preconfig</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">PyConfig</span> <span class="pre">config</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">PyStatus</span> <span class="pre">status</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">struct</span> <span class="pre">_inittab</span> <span class="pre">*inittab</span></code> for <code class="docutils literal notranslate"><span class="pre">PyInitConfig_AddModule()</span></code></li>
</ul>
<p>The <code class="docutils literal notranslate"><span class="pre">PyStatus</span></code> status is no longer separated, but part of the unified
<code class="docutils literal notranslate"><span class="pre">PyInitConfig</span></code> structure, which makes the API easier to use.</p>
</section>
<section id="configuration-options">
<h3><a class="toc-backref" href="#configuration-options" role="doc-backlink">Configuration Options</a></h3>
<p>Configuration options are named after <code class="docutils literal notranslate"><span class="pre">PyPreConfig</span></code> and <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code>
structure members. See the <a class="reference external" href="https://docs.python.org/dev/c-api/init_config.html#pypreconfig">PyPreConfig documentation</a> and
the <a class="reference external" href="https://docs.python.org/dev/c-api/init_config.html#pyconfig">PyConfig documentation</a>.</p>
<p>Deprecating and removing configuration options is out of the scope of
the PEP and should be discussed on a case by case basis.</p>
<section id="public-configuration-options">
<h4><a class="toc-backref" href="#public-configuration-options" role="doc-backlink">Public configuration options</a></h4>
<p>Following options can be get by <code class="docutils literal notranslate"><span class="pre">PyConfig_Get()</span></code> and set and
<code class="docutils literal notranslate"><span class="pre">PyConfig_Set()</span></code>.</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 22.2%" />
<col style="width: 22.2%" />
<col style="width: 55.6%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head">Option</th>
<th class="head">Type</th>
<th class="head">Comment</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">argv</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">list[str]</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.argv</span></code>.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">base_exec_prefix</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.base_exec_prefix</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">base_executable</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys._base_executable</span></code>.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">base_prefix</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.base_prefix</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">bytes_warning</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">int</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.bytes_warning</span></code>.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">exec_prefix</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.exec_prefix</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">executable</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.executable</span></code>.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">inspect</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.inspect</span></code> (<code class="docutils literal notranslate"><span class="pre">int</span></code>).</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">int_max_str_digits</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">int</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.int_max_str_digits</span></code>,
<code class="docutils literal notranslate"><span class="pre">sys.get_int_max_str_digits()</span></code> and
<code class="docutils literal notranslate"><span class="pre">sys.set_int_max_str_digits()</span></code>.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">interactive</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.interactive</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">module_search_paths</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">list[str]</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.path</span></code>.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">optimization_level</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">int</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.optimize</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">parser_debug</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.debug</span></code> (<code class="docutils literal notranslate"><span class="pre">int</span></code>).</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">platlibdir</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.platlibdir</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">prefix</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.base_prefix</span></code>.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">pycache_prefix</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.pycache_prefix</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">quiet</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.quiet</span></code> (<code class="docutils literal notranslate"><span class="pre">int</span></code>).</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">stdlib_dir</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys._stdlib_dir</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">use_environment</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.ignore_environment</span></code> (<code class="docutils literal notranslate"><span class="pre">int</span></code>).</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">verbose</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">int</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.verbose</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">warnoptions</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">list[str]</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.warnoptions</span></code>.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">write_bytecode</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.dont_write_bytecode</span></code> (<code class="docutils literal notranslate"><span class="pre">int</span></code>) and <code class="docutils literal notranslate"><span class="pre">sys.dont_write_bytecode</span></code> (<code class="docutils literal notranslate"><span class="pre">bool</span></code>).</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">xoptions</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">dict[str,</span> <span class="pre">str]</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys._xoptions</span></code>.</td>
</tr>
</tbody>
</table>
<p>Some option names are different than <code class="docutils literal notranslate"><span class="pre">sys</span></code> attributes, such as
<code class="docutils literal notranslate"><span class="pre">optimization_level</span></code> option and <code class="docutils literal notranslate"><span class="pre">sys.flags.optimize</span></code> attribute.
<code class="docutils literal notranslate"><span class="pre">PyConfig_Set()</span></code> sets the corresponding <code class="docutils literal notranslate"><span class="pre">sys</span></code> attribute.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">xoptions</span></code> is a list of strings in <code class="docutils literal notranslate"><span class="pre">PyInitConfig</span></code> where each
string has the format <code class="docutils literal notranslate"><span class="pre">key</span></code> (<em>value</em> is <code class="docutils literal notranslate"><span class="pre">True</span></code> implicitly) or
<code class="docutils literal notranslate"><span class="pre">key=value</span></code>. In the current runtime configuration, it becomes a
dictionary (<code class="docutils literal notranslate"><span class="pre">key:</span> <span class="pre">str</span></code><code class="docutils literal notranslate"><span class="pre">value:</span> <span class="pre">str</span> <span class="pre">|</span> <span class="pre">True</span></code>).</p>
</section>
<section id="read-only-configuration-options">
<h4><a class="toc-backref" href="#read-only-configuration-options" role="doc-backlink">Read-only configuration options</a></h4>
<p>Following options can be get by <code class="docutils literal notranslate"><span class="pre">PyConfig_Get()</span></code>, but cannot be set by
<code class="docutils literal notranslate"><span class="pre">PyConfig_Set()</span></code>.</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 22.2%" />
<col style="width: 22.2%" />
<col style="width: 55.6%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head">Option</th>
<th class="head">Type</th>
<th class="head">Comment</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">allocator</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">int</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">buffered_stdio</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">check_hash_pycs_mode</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">code_debug_ranges</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">coerce_c_locale</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">coerce_c_locale_warn</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">configure_c_stdio</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">configure_locale</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">cpu_count</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">int</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">os.cpu_count()</span></code> (<code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">|</span> <span class="pre">None</span></code>).</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">dev_mode</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.dev_mode</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">dump_refs</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">dump_refs_file</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">faulthandler</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">faulthandler.is_enabled()</span></code>.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">filesystem_encoding</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.getfilesystemencoding()</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">filesystem_errors</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.getfilesystemencodeerrors()</span></code>.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">hash_seed</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">int</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">home</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">import_time</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">install_signal_handlers</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">isolated</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.isolated</span></code> (<code class="docutils literal notranslate"><span class="pre">int</span></code>).</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">legacy_windows_fs_encoding</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>Windows only.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">legacy_windows_stdio</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>Windows only.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">malloc_stats</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">orig_argv</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">list[str]</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.orig_argv</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">parse_argv</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">pathconfig_warnings</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">perf_profiling</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.is_stack_trampoline_active()</span></code>.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">program_name</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">run_command</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">run_filename</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">run_module</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">run_presite</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>need a debug build.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">safe_path</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">show_ref_count</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">site_import</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.no_site</span></code> (<code class="docutils literal notranslate"><span class="pre">int</span></code>).</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">skip_source_first_line</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">stdio_encoding</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.stdin.encoding</span></code>, <code class="docutils literal notranslate"><span class="pre">sys.stdout.encoding</span></code> and
<code class="docutils literal notranslate"><span class="pre">sys.stderr.encoding</span></code>.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">stdio_errors</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">str</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.stdin.errors</span></code>, <code class="docutils literal notranslate"><span class="pre">sys.stdout.errors</span></code> and
<code class="docutils literal notranslate"><span class="pre">sys.stderr.errors</span></code>.</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">tracemalloc</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">int</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">tracemalloc.is_tracing()</span></code> (<code class="docutils literal notranslate"><span class="pre">bool</span></code>).</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">use_frozen_modules</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">use_hash_seed</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">user_site_directory</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys.flags.no_user_site</span></code> (<code class="docutils literal notranslate"><span class="pre">int</span></code>).</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">utf8_mode</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">warn_default_encoding</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">_pystats</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">bool</span></code></td>
<td>API: <code class="docutils literal notranslate"><span class="pre">sys._stats_on()</span></code>, <code class="docutils literal notranslate"><span class="pre">sys._stats_off()</span></code>.
Need a <code class="docutils literal notranslate"><span class="pre">Py_STATS</span></code> build.</td>
</tr>
</tbody>
</table>
</section>
</section>
<section id="create-config">
<h3><a class="toc-backref" href="#create-config" role="doc-backlink">Create Config</a></h3>
<dl>
<dt><code class="docutils literal notranslate"><span class="pre">PyInitConfig</span></code> structure:</dt><dd>Opaque structure to configure the Python preinitialization and the
Python initialization.</dd>
<dt><code class="docutils literal notranslate"><span class="pre">PyInitConfig*</span> <span class="pre">PyInitConfig_Create(void)</span></code>:</dt><dd>Create a new initialization configuration using default values
of the <a class="reference external" href="https://docs.python.org/dev/c-api/init_config.html#isolated-configuration">Isolated Configuration</a>.<p>It must be freed with <code class="docutils literal notranslate"><span class="pre">PyInitConfig_Free()</span></code>.</p>
<p>Return <code class="docutils literal notranslate"><span class="pre">NULL</span></code> on memory allocation failure.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">PyInitConfig_Free(PyInitConfig</span> <span class="pre">*config)</span></code>:</dt><dd>Free memory of an initialization configuration.</dd>
</dl>
</section>
<section id="get-options">
<h3><a class="toc-backref" href="#get-options" role="doc-backlink">Get Options</a></h3>
<p>The configuration option <em>name</em> parameter must be a non-NULL
null-terminated UTF-8 encoded string.</p>
<dl>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyInitConfig_HasOption(PyInitConfig</span> <span class="pre">*config,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name)</span></code>:</dt><dd>Test if the configuration has an option called <em>name</em>.<p>Return <code class="docutils literal notranslate"><span class="pre">1</span></code> if the option exists, or return <code class="docutils literal notranslate"><span class="pre">0</span></code> otherwise.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyInitConfig_GetInt(PyInitConfig</span> <span class="pre">*config,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name,</span> <span class="pre">int64_t</span> <span class="pre">*value)</span></code>:</dt><dd>Get an integer configuration option.<ul class="simple">
<li>Set <em>*value</em>, and return <code class="docutils literal notranslate"><span class="pre">0</span></code> on success.</li>
<li>Set an error in <em>config</em> and return <code class="docutils literal notranslate"><span class="pre">-1</span></code> on error.</li>
</ul>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyInitConfig_GetStr(PyInitConfig</span> <span class="pre">*config,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name,</span> <span class="pre">char</span> <span class="pre">**value)</span></code>:</dt><dd>Get a string configuration option as a null-terminated UTF-8
encoded string.<ul class="simple">
<li>Set <em>*value</em>, and return <code class="docutils literal notranslate"><span class="pre">0</span></code> on success.</li>
<li>Set an error in <em>config</em> and return <code class="docutils literal notranslate"><span class="pre">-1</span></code> on error.</li>
</ul>
<p>On success, the string must be released with <code class="docutils literal notranslate"><span class="pre">free(value)</span></code>.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyInitConfig_GetStrList(PyInitConfig</span> <span class="pre">*config,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name,</span> <span class="pre">size_t</span> <span class="pre">*length,</span> <span class="pre">char</span> <span class="pre">***items)</span></code>:</dt><dd>Get a string list configuration option as an array of
null-terminated UTF-8 encoded strings.<ul class="simple">
<li>Set <em>*length</em> and <em>*value</em>, and return <code class="docutils literal notranslate"><span class="pre">0</span></code> on success.</li>
<li>Set an error in <em>config</em> and return <code class="docutils literal notranslate"><span class="pre">-1</span></code> on error.</li>
</ul>
<p>On success, the string list must be released with
<code class="docutils literal notranslate"><span class="pre">PyInitConfig_FreeStrList(length,</span> <span class="pre">items)</span></code>.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">PyInitConfig_FreeStrList(size_t</span> <span class="pre">length,</span> <span class="pre">char</span> <span class="pre">**items)</span></code>:</dt><dd>Free memory of a string list created by
<code class="docutils literal notranslate"><span class="pre">PyInitConfig_GetStrList()</span></code>.</dd>
</dl>
</section>
<section id="set-options">
<h3><a class="toc-backref" href="#set-options" role="doc-backlink">Set Options</a></h3>
<p>The configuration option <em>name</em> parameter must be a non-NULL
null-terminated UTF-8 encoded string.</p>
<p>Some configuration options have side effects on other options. This
logic is only implemented when <code class="docutils literal notranslate"><span class="pre">Py_InitializeFromInitConfig()</span></code> is
called, not by the “Set” functions below. For example, setting
<code class="docutils literal notranslate"><span class="pre">dev_mode</span></code> to <code class="docutils literal notranslate"><span class="pre">1</span></code> does not set <code class="docutils literal notranslate"><span class="pre">faulthandler</span></code> to <code class="docutils literal notranslate"><span class="pre">1</span></code>.</p>
<dl>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyInitConfig_SetInt(PyInitConfig</span> <span class="pre">*config,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name,</span> <span class="pre">int64_t</span> <span class="pre">value)</span></code>:</dt><dd>Set an integer configuration option.<ul class="simple">
<li>Return <code class="docutils literal notranslate"><span class="pre">0</span></code> on success.</li>
<li>Set an error in <em>config</em> and return <code class="docutils literal notranslate"><span class="pre">-1</span></code> on error.</li>
</ul>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyInitConfig_SetStr(PyInitConfig</span> <span class="pre">*config,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*value)</span></code>:</dt><dd>Set a string configuration option from a null-terminated UTF-8
encoded string. The string is copied.<ul class="simple">
<li>Return <code class="docutils literal notranslate"><span class="pre">0</span></code> on success.</li>
<li>Set an error in <em>config</em> and return <code class="docutils literal notranslate"><span class="pre">-1</span></code> on error.</li>
</ul>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyInitConfig_SetStrList(PyInitConfig</span> <span class="pre">*config,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name,</span> <span class="pre">size_t</span> <span class="pre">length,</span> <span class="pre">char</span> <span class="pre">*</span> <span class="pre">const</span> <span class="pre">*items)</span></code>:</dt><dd>Set a string list configuration option from an array of
null-terminated UTF-8 encoded strings. The string list is copied.<ul class="simple">
<li>Return <code class="docutils literal notranslate"><span class="pre">0</span></code> on success.</li>
<li>Set an error in <em>config</em> and return <code class="docutils literal notranslate"><span class="pre">-1</span></code> on error.</li>
</ul>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyInitConfig_AddModule(PyInitConfig</span> <span class="pre">*config,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name,</span> <span class="pre">PyObject*</span> <span class="pre">(*initfunc)(void))</span></code>:</dt><dd>Add a built-in extension module to the table of built-in modules.<p>The new module can be imported by the name <em>name</em>, and uses the
function <em>initfunc</em> as the initialization function called on the
first attempted import.</p>
<ul class="simple">
<li>Return <code class="docutils literal notranslate"><span class="pre">0</span></code> on success.</li>
<li>Set an error in <em>config</em> and return <code class="docutils literal notranslate"><span class="pre">-1</span></code> on error.</li>
</ul>
<p>If Python is initialized multiple times,
<code class="docutils literal notranslate"><span class="pre">PyInitConfig_AddModule()</span></code> must be called at each Python
initialization.</p>
<p>Similar to the <code class="docutils literal notranslate"><span class="pre">PyImport_AppendInittab()</span></code> function.</p>
</dd>
</dl>
</section>
<section id="initialize-python">
<h3><a class="toc-backref" href="#initialize-python" role="doc-backlink">Initialize Python</a></h3>
<dl>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">Py_InitializeFromInitConfig(PyInitConfig</span> <span class="pre">*config)</span></code>:</dt><dd>Initialize Python from the initialization configuration.<ul class="simple">
<li>Return <code class="docutils literal notranslate"><span class="pre">0</span></code> on success.</li>
<li>Set an error in <em>config</em> and return <code class="docutils literal notranslate"><span class="pre">-1</span></code> on error.</li>
<li>Set an exit code in <em>config</em> and return <code class="docutils literal notranslate"><span class="pre">-1</span></code> if Python wants to
exit.</li>
</ul>
<p>See <code class="docutils literal notranslate"><span class="pre">PyInitConfig_GetExitcode()</span></code> for the exitcode case.</p>
</dd>
</dl>
</section>
<section id="error-handling">
<h3><a class="toc-backref" href="#error-handling" role="doc-backlink">Error Handling</a></h3>
<dl>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyInitConfig_GetError(PyInitConfig*</span> <span class="pre">config,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">**err_msg)</span></code>:</dt><dd>Get the <em>config</em> error message.<ul class="simple">
<li>Set <em>*err_msg</em> and return <code class="docutils literal notranslate"><span class="pre">1</span></code> if an error is set.</li>
<li>Set <em>*err_msg</em> to <code class="docutils literal notranslate"><span class="pre">NULL</span></code> and return <code class="docutils literal notranslate"><span class="pre">0</span></code> otherwise.</li>
</ul>
<p>An error message is an UTF-8 encoded string.</p>
<p>If <em>config</em> has an exit code, format the exit code as an error
message.</p>
<p>The error message remains valid until another <code class="docutils literal notranslate"><span class="pre">PyInitConfig</span></code>
function is called with <em>config</em>. The caller doesnt have to free the
error message.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyInitConfig_GetExitcode(PyInitConfig*</span> <span class="pre">config,</span> <span class="pre">int</span> <span class="pre">*exitcode)</span></code>:</dt><dd>Get the <em>config</em> exit code.<ul class="simple">
<li>Set <em>*exitcode</em> and return <code class="docutils literal notranslate"><span class="pre">1</span></code> if Python wants to exit.</li>
<li>Return <code class="docutils literal notranslate"><span class="pre">0</span></code> if <em>config</em> has no exit code set.</li>
</ul>
<p>Only the <code class="docutils literal notranslate"><span class="pre">Py_InitializeFromInitConfig()</span></code> function can set an exit
code if the <code class="docutils literal notranslate"><span class="pre">parse_argv</span></code> option is non-zero.</p>
<p>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).</p>
</dd>
</dl>
</section>
<section id="get-and-set-the-runtime-configuration">
<h3><a class="toc-backref" href="#get-and-set-the-runtime-configuration" role="doc-backlink">Get and Set the Runtime Configuration</a></h3>
<p>The configuration option <em>name</em> parameter must be a non-NULL
null-terminated UTF-8 encoded string.</p>
<dl>
<dt><code class="docutils literal notranslate"><span class="pre">PyObject*</span> <span class="pre">PyConfig_Get(const</span> <span class="pre">char</span> <span class="pre">*name)</span></code>:</dt><dd>Get the current runtime value of a configuration option as a Python
object.<ul class="simple">
<li>Return a new reference on success.</li>
<li>Set an exception and return <code class="docutils literal notranslate"><span class="pre">NULL</span></code> on error.</li>
</ul>
<p>The object type depends on the option: see <a class="reference internal" href="#configuration-options">Configuration Options</a>
tables.</p>
<p>Other options are get from internal <code class="docutils literal notranslate"><span class="pre">PyPreConfig</span></code> and <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code> structures.</p>
<p>The caller must hold the GIL. The function cannot be called before
Python initialization nor after Python finalization.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyConfig_GetInt(const</span> <span class="pre">char</span> <span class="pre">*name,</span> <span class="pre">int</span> <span class="pre">*value)</span></code>:</dt><dd>Similar to <code class="docutils literal notranslate"><span class="pre">PyConfig_Get()</span></code>, but get the value as an integer.<ul class="simple">
<li>Set <code class="docutils literal notranslate"><span class="pre">*value</span></code> and return <code class="docutils literal notranslate"><span class="pre">0</span></code> success.</li>
<li>Set an exception and return <code class="docutils literal notranslate"><span class="pre">-1</span></code> on error.</li>
</ul>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">PyObject*</span> <span class="pre">PyConfig_Names(void)</span></code>:</dt><dd>Get all configuration option names as a <code class="docutils literal notranslate"><span class="pre">frozenset</span></code>.<p>Set an exception and return <code class="docutils literal notranslate"><span class="pre">NULL</span></code> on error.</p>
<p>The caller must hold the GIL.</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">PyObject*</span> <span class="pre">PyConfig_Set(const</span> <span class="pre">char</span> <span class="pre">*name,</span> <span class="pre">PyObject</span> <span class="pre">*value)</span></code>:</dt><dd>Set the current runtime value of a configuration option.<ul class="simple">
<li>Raise a <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> if there is no option <em>name</em>.</li>
<li>Raise a <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> if <em>value</em> is an invalid value.</li>
<li>Raise a <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> if the option is read-only: cannot be set.</li>
<li>Raise a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> if <em>value</em> has not the proper type.</li>
</ul>
<p><a class="reference internal" href="#read-only-configuration-options">Read-only configuration options</a> cannot be set.</p>
<p>The caller must hold the GIL. The function cannot be called before
Python initialization nor after Python finalization.</p>
</dd>
</dl>
</section>
<section id="stability">
<h3><a class="toc-backref" href="#stability" role="doc-backlink">Stability</a></h3>
<p>The behavior of options, the default option values, and the Python
behavior can change at each Python version: they are not “stable”.</p>
<p>Moreover, configuration options can be added, deprecated and removed
following the usual <a class="pep reference internal" href="../pep-0387/" title="PEP 387 Backwards Compatibility Policy">PEP 387</a> deprecation process.</p>
</section>
<section id="interaction-with-the-pypreconfig-and-pyconfig-apis">
<h3><a class="toc-backref" href="#interaction-with-the-pypreconfig-and-pyconfig-apis" role="doc-backlink">Interaction with the PyPreConfig and PyConfig APIs</a></h3>
<p>The lower level <a class="pep reference internal" href="../pep-0587/" title="PEP 587 Python Initialization Configuration">PEP 587</a> <code class="docutils literal notranslate"><span class="pre">PyPreConfig</span></code> and <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code> APIs remain
available and fully supported. As noted in the Abstract, they remain the
preferred approach for embedding use cases that are aiming to closely
emulate the behaviour of the full CPython CLI, rather than just making a
Python runtime available as part of a larger application.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">PyPreConfig</span></code> APIs may be used in combination with the
initialization API in this PEP. In such cases, the read-only vs
read/write restrictions for preconfiguration settings apply to
<code class="docutils literal notranslate"><span class="pre">PyInitConfig_SetInt</span></code> in addition to <code class="docutils literal notranslate"><span class="pre">PyConfig_Set</span></code> once the
interpreter has been preconfigured (specifically, only
<code class="docutils literal notranslate"><span class="pre">use_environment</span></code> may be updated, attempting to update any of the
other preconfiguration variables will report an error).</p>
</section>
</section>
<section id="examples">
<h2><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h2>
<section id="id1">
<h3><a class="toc-backref" href="#id1" role="doc-backlink">Initialize Python</a></h3>
<p>Example initializing Python, set configuration options of various types,
return <code class="docutils literal notranslate"><span class="pre">-1</span></code> on error:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="nf">init_python</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">PyInitConfig</span><span class="w"> </span><span class="o">*</span><span class="n">config</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyInitConfig_Create</span><span class="p">();</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">config</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">&quot;PYTHON INIT ERROR: memory allocation failed</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1">// Set an integer (dev mode)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">PyInitConfig_SetInt</span><span class="p">(</span><span class="n">config</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;dev_mode&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">goto</span><span class="w"> </span><span class="n">error</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1">// Set a list of UTF-8 strings (argv)</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">argv</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="s">&quot;my_program&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;-c&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;pass&quot;</span><span class="p">};</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">PyInitConfig_SetStrList</span><span class="p">(</span><span class="n">config</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;argv&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="n">Py_ARRAY_LENGTH</span><span class="p">(</span><span class="n">argv</span><span class="p">),</span><span class="w"> </span><span class="n">argv</span><span class="p">)</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">goto</span><span class="w"> </span><span class="n">error</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1">// Set a UTF-8 string (program name)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">PyInitConfig_SetStr</span><span class="p">(</span><span class="n">config</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;program_name&quot;</span><span class="p">,</span><span class="w"> </span><span class="sa">L</span><span class="s">&quot;my_program&quot;</span><span class="p">)</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">goto</span><span class="w"> </span><span class="n">error</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1">// Initialize Python with the configuration</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">Py_InitializeFromInitConfig</span><span class="p">(</span><span class="n">config</span><span class="p">)</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">goto</span><span class="w"> </span><span class="n">error</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">PyInitConfig_Free</span><span class="p">(</span><span class="n">config</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="nl">error</span><span class="p">:</span>
<span class="w"> </span><span class="c1">// Display the error message</span>
<span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">err_msg</span><span class="p">;</span>
<span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="n">PyInitConfig_GetError</span><span class="p">(</span><span class="n">config</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">err_msg</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">&quot;PYTHON INIT ERROR: %s</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">err_msg</span><span class="p">);</span>
<span class="w"> </span><span class="n">PyInitConfig_Free</span><span class="p">(</span><span class="n">config</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
<section id="increase-initialization-bytes-warning-option">
<h3><a class="toc-backref" href="#increase-initialization-bytes-warning-option" role="doc-backlink">Increase initialization bytes_warning option</a></h3>
<p>Example increasing the <code class="docutils literal notranslate"><span class="pre">bytes_warning</span></code> option of an initialization
configuration:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="nf">config_bytes_warning</span><span class="p">(</span><span class="n">PyInitConfig</span><span class="w"> </span><span class="o">*</span><span class="n">config</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">int64_t</span><span class="w"> </span><span class="n">bytes_warning</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">PyInitConfig_GetInt</span><span class="p">(</span><span class="n">config</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;bytes_warning&quot;</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">bytes_warning</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">bytes_warning</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">PyInitConfig_SetInt</span><span class="p">(</span><span class="n">config</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;bytes_warning&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">bytes_warning</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
<section id="get-the-runtime-verbose-option">
<h3><a class="toc-backref" href="#get-the-runtime-verbose-option" role="doc-backlink">Get the runtime verbose option</a></h3>
<p>Example getting the current runtime value of the configuration option
<code class="docutils literal notranslate"><span class="pre">verbose</span></code>:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span><span class="w"> </span><span class="nf">get_verbose</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">verbose</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">PyConfig_GetInt</span><span class="p">(</span><span class="s">&quot;verbose&quot;</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">verbose</span><span class="p">)</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Silently ignore the error</span>
<span class="w"> </span><span class="n">PyErr_Clear</span><span class="p">();</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">verbose</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>On error, the function silently ignores the error and returns <code class="docutils literal notranslate"><span class="pre">-1</span></code>. In
practice, getting the <code class="docutils literal notranslate"><span class="pre">verbose</span></code> option cannot fail, unless a future
Python version removes the option.</p>
</section>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<ul class="simple">
<li>Issue: <a class="reference external" href="https://github.com/python/cpython/issues/107954">[C API] PEP 741: Add PyInitConfig C API to customize
the Python initialization</a></li>
<li>PR: <a class="reference external" href="https://github.com/python/cpython/pull/123472">Add PyConfig_Get() function</a></li>
<li>PR: <a class="reference external" href="https://github.com/python/cpython/pull/123502">Add PyInitConfig C API</a></li>
</ul>
</section>
<section id="backwards-compatibility">
<h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2>
<p>Changes are fully backward compatible. Only new APIs are added.</p>
<p>Existing API such as the <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code> C API (PEP 587) are left
unchanged.</p>
</section>
<section id="rejected-ideas">
<h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2>
<section id="configuration-as-text">
<h3><a class="toc-backref" href="#configuration-as-text" role="doc-backlink">Configuration as text</a></h3>
<p>It was proposed to provide the configuration as text to make the API
compatible with the stable ABI and to allow custom options.</p>
<p>Example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># integer</span>
<span class="n">bytes_warning</span> <span class="o">=</span> <span class="mi">2</span>
<span class="c1"># string</span>
<span class="n">filesystem_encoding</span> <span class="o">=</span> <span class="s2">&quot;utf8&quot;</span> <span class="c1"># comment</span>
<span class="c1"># list of strings</span>
<span class="n">argv</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;python&#39;</span><span class="p">,</span> <span class="s1">&#39;-c&#39;</span><span class="p">,</span> <span class="s1">&#39;code&#39;</span><span class="p">]</span>
</pre></div>
</div>
<p>The API would take the configuration as a string, not as a file. Example
with a hypothetical <code class="docutils literal notranslate"><span class="pre">PyInit_SetConfig()</span></code> function:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">void</span><span class="w"> </span><span class="nf">stable_abi_init_demo</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">set_path</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">PyInit_SetConfig</span><span class="p">(</span>
<span class="w"> </span><span class="s">&quot;isolated = 1</span><span class="se">\n</span><span class="s">&quot;</span>
<span class="w"> </span><span class="s">&quot;argv = [&#39;python&#39;, &#39;-c&#39;, &#39;code&#39;]</span><span class="se">\n</span><span class="s">&quot;</span>
<span class="w"> </span><span class="s">&quot;filesystem_encoding = &#39;utf-8&#39;</span><span class="se">\n</span><span class="s">&quot;</span>
<span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">set_path</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">PyInit_SetConfig</span><span class="p">(</span><span class="s">&quot;pythonpath = &#39;/my/path&#39;&quot;</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The example ignores error handling to make it easier to read.</p>
<p>The problem is that generating such configuration text requires adding
quotes to strings and to escape quotes in strings. Formatting an array
of strings becomes non-trivial.</p>
<p>Providing an API to format a string or an array of strings is not really
worth it, whereas Python can provide directly an API to set a
configuration option where the value is passed directly as a string or
an array of strings. It avoids giving special meaning to some
characters, such as newline characters, which would have to be escaped.</p>
</section>
<section id="refer-to-an-option-with-an-integer">
<h3><a class="toc-backref" href="#refer-to-an-option-with-an-integer" role="doc-backlink">Refer to an option with an integer</a></h3>
<p>Using strings to refer to a configuration option requires comparing
strings which can be slower than comparing integers.</p>
<p>Use integers, similar to type “slots” such as <code class="docutils literal notranslate"><span class="pre">Py_tp_doc</span></code>, to refer to
a configuration option. The <code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*name</span></code> parameter is replaced
with <code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">option</span></code>.</p>
<p>Accepting custom options is more likely to cause conflicts when using
integers, since its harder to maintain “namespaces” (ranges) for
integer options. Using strings, a simple prefix with a colon separator
can be used.</p>
<p>Integers also requires maintaining a list of integer constants and so
make the C API and the Python API larger.</p>
<p>Python 3.13 only has around 62 configuration options, and so performance
is not really a blocker issue. If better performance is needed later, a
hash table can be used to get an option by its name.</p>
<p>If getting a configuration option is used in hot code, the value can be
read once and cached. By the way, most configuration options cannot be
changed at runtime.</p>
</section>
<section id="multi-phase-initialization-similar-to-pep-432">
<h3><a class="toc-backref" href="#multi-phase-initialization-similar-to-pep-432" role="doc-backlink">Multi-phase initialization (similar to PEP 432)</a></h3>
<p><a class="reference external" href="https://discuss.python.org/t/pep-741-python-configuration-c-api-second-version/45403/27">Eric Snow expressed concerns</a>
that this proposal might reinforce with embedders the idea that
initialization is a single monolithic step. He argued that initialization
involves 5 distinct phases and even suggested that the API should
reflect this explicitly. Eric proposed that, at the very least, the
implementation of initialization should reflect the phases, in part
for improved code health. Overall, his explanation has some
similarities with <a class="pep reference internal" href="../pep-0432/" title="PEP 432 Restructuring the CPython startup sequence">PEP 432</a> and <a class="pep reference internal" href="../pep-0587/" title="PEP 587 Python Initialization Configuration">PEP 587</a>.</p>
<p>Another of Erics key points relevant to this PEP was that, ideally,
the config passed to <code class="docutils literal notranslate"><span class="pre">Py_InitializeFromConfig()</span></code> should be complete
before that function is called, whereas currently initialization
actually modifies the config.</p>
<p>While Eric wasnt necessarily suggesting an alternative to PEP 741,
any proposal to add a granular initialization API around phases is
effectively the opposite of what this PEP is trying to accomplish.
Such API is more complicated, it requires adding new public structures
and new public functions. It makes the Python initialization more
complicated, rather than this PEP tries to unify existing APIs and make
them simpler (the opposite). Having multiple structures for similar
purpose can lead to duplicate members, similar issue than duplicated
members between existing <code class="docutils literal notranslate"><span class="pre">PyPreConfig</span></code> and <code class="docutils literal notranslate"><span class="pre">PyConfig</span></code> structures.</p>
</section>
<section id="locale-encoding-and-wide-strings">
<h3><a class="toc-backref" href="#locale-encoding-and-wide-strings" role="doc-backlink">Locale encoding and wide strings</a></h3>
<p>Accepting strings encoded to the locale encoding and accepting wide
strings (<code class="docutils literal notranslate"><span class="pre">wchar_t*</span></code>) in the <code class="docutils literal notranslate"><span class="pre">PyInitConfig</span></code> API was deferred to keep
the <code class="docutils literal notranslate"><span class="pre">PyInitConfig</span></code> API simple and avoid the complexity of the Python
preinitialization. These features are also mostly needed when emulating
the full CPython CLI behaviour, and hence better served by the lower
level <a class="pep reference internal" href="../pep-0587/" title="PEP 587 Python Initialization Configuration">PEP 587</a> API.</p>
</section>
</section>
<section id="discussions">
<h2><a class="toc-backref" href="#discussions" role="doc-backlink">Discussions</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://discuss.python.org/t/pep-741-python-configuration-c-api-second-version/45403">PEP 741: Python Configuration C API (second version)</a>
(February 2024).</li>
<li><a class="reference external" href="https://discuss.python.org/t/pep-741-python-configuration-c-api/43637">PEP 741: Python Configuration C API</a>
(January 2024).</li>
<li><a class="reference external" href="https://discuss.python.org/t/fr-allow-private-runtime-config-to-enable-extending-without-breaking-the-pyconfig-abi/18004">FR: Allow private runtime config to enable extending without breaking
the PyConfig ABI</a>
(August 2022).</li>
</ul>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0741.rst">https://github.com/python/peps/blob/main/peps/pep-0741.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0741.rst">2024-09-03 13:37:25 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
<li><a class="reference internal" href="#get-the-runtime-configuration">Get the runtime configuration</a></li>
<li><a class="reference internal" href="#security-fix">Security fix</a></li>
<li><a class="reference internal" href="#redundancy-between-pypreconfig-and-pyconfig">Redundancy between PyPreConfig and PyConfig</a></li>
<li><a class="reference internal" href="#embedding-python">Embedding Python</a><ul>
<li><a class="reference internal" href="#applications-embedding-python">Applications embedding Python</a></li>
<li><a class="reference internal" href="#libraries-embedding-python">Libraries embedding Python</a></li>
<li><a class="reference internal" href="#utilities-creating-standalone-applications">Utilities creating standalone applications</a></li>
</ul>
</li>
<li><a class="reference internal" href="#set-the-runtime-configuration">Set the runtime configuration</a></li>
</ul>
</li>
<li><a class="reference internal" href="#specification">Specification</a><ul>
<li><a class="reference internal" href="#pyinitconfig-structure">PyInitConfig structure</a></li>
<li><a class="reference internal" href="#configuration-options">Configuration Options</a><ul>
<li><a class="reference internal" href="#public-configuration-options">Public configuration options</a></li>
<li><a class="reference internal" href="#read-only-configuration-options">Read-only configuration options</a></li>
</ul>
</li>
<li><a class="reference internal" href="#create-config">Create Config</a></li>
<li><a class="reference internal" href="#get-options">Get Options</a></li>
<li><a class="reference internal" href="#set-options">Set Options</a></li>
<li><a class="reference internal" href="#initialize-python">Initialize Python</a></li>
<li><a class="reference internal" href="#error-handling">Error Handling</a></li>
<li><a class="reference internal" href="#get-and-set-the-runtime-configuration">Get and Set the Runtime Configuration</a></li>
<li><a class="reference internal" href="#stability">Stability</a></li>
<li><a class="reference internal" href="#interaction-with-the-pypreconfig-and-pyconfig-apis">Interaction with the PyPreConfig and PyConfig APIs</a></li>
</ul>
</li>
<li><a class="reference internal" href="#examples">Examples</a><ul>
<li><a class="reference internal" href="#id1">Initialize Python</a></li>
<li><a class="reference internal" href="#increase-initialization-bytes-warning-option">Increase initialization bytes_warning option</a></li>
<li><a class="reference internal" href="#get-the-runtime-verbose-option">Get the runtime verbose option</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul>
<li><a class="reference internal" href="#configuration-as-text">Configuration as text</a></li>
<li><a class="reference internal" href="#refer-to-an-option-with-an-integer">Refer to an option with an integer</a></li>
<li><a class="reference internal" href="#multi-phase-initialization-similar-to-pep-432">Multi-phase initialization (similar to PEP 432)</a></li>
<li><a class="reference internal" href="#locale-encoding-and-wide-strings">Locale encoding and wide strings</a></li>
</ul>
</li>
<li><a class="reference internal" href="#discussions">Discussions</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0741.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>