Python-checkins
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
January 2025
- 1 participants
- 525 discussions
gh-128360: Add `_Py_AssertHoldsTstate` as assertion for holding a thread state (#128361)
by kumaraditya303 Jan. 20, 2025
by kumaraditya303 Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/4d0a6595a06c554c57ebd90ee64ff4c2be…
commit: 4d0a6595a06c554c57ebd90ee64ff4c2bec239b8
branch: main
author: Peter Bierma <zintensitydev(a)gmail.com>
committer: kumaraditya303 <kumaraditya(a)python.org>
date: 2025-01-20T17:04:35+05:30
summary:
gh-128360: Add `_Py_AssertHoldsTstate` as assertion for holding a thread state (#128361)
Co-authored-by: Kumar Aditya <kumaraditya(a)python.org>
files:
M Include/internal/pycore_pystate.h
M Modules/socketmodule.c
M Objects/object.c
M Objects/obmalloc.c
M Python/ceval_gil.c
M Python/errors.c
M Python/fileutils.c
M Python/legacy_tracing.c
M Python/pystate.c
M Python/pytime.c
M Python/tracemalloc.c
diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h
index 1e73e541ef8de0..ff3b222b157810 100644
--- a/Include/internal/pycore_pystate.h
+++ b/Include/internal/pycore_pystate.h
@@ -300,6 +300,19 @@ PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void);
// See also PyInterpreterState_Get() and _PyInterpreterState_GET().
extern PyInterpreterState* _PyGILState_GetInterpreterStateUnsafe(void);
+#ifndef NDEBUG
+/* Modern equivalent of assert(PyGILState_Check()) */
+static inline void
+_Py_AssertHoldsTstateFunc(const char *func)
+{
+ PyThreadState *tstate = _PyThreadState_GET();
+ _Py_EnsureFuncTstateNotNULL(func, tstate);
+}
+#define _Py_AssertHoldsTstate() _Py_AssertHoldsTstateFunc(__func__)
+#else
+#define _Py_AssertHoldsTstate()
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index e70aa304f2f3a3..5e81253ca4a591 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -110,6 +110,7 @@ Local naming conventions:
#include "pycore_fileutils.h" // _Py_set_inheritable()
#include "pycore_moduleobject.h" // _PyModule_GetState
#include "pycore_time.h" // _PyTime_AsMilliseconds()
+#include "pycore_pystate.h" // _Py_AssertHoldsTstate()
#include "pycore_pyatomic_ft_wrappers.h"
#ifdef _Py_MEMORY_SANITIZER
@@ -822,8 +823,8 @@ internal_select(PySocketSockObject *s, int writing, PyTime_t interval,
struct timeval tv, *tvp;
#endif
- /* must be called with the GIL held */
- assert(PyGILState_Check());
+ /* must be called with a thread state */
+ _Py_AssertHoldsTstate();
/* Error condition is for output only */
assert(!(connect && !writing));
@@ -936,8 +937,8 @@ sock_call_ex(PySocketSockObject *s,
int deadline_initialized = 0;
int res;
- /* sock_call() must be called with the GIL held. */
- assert(PyGILState_Check());
+ /* sock_call() must be called with a thread state. */
+ _Py_AssertHoldsTstate();
/* outer loop to retry select() when select() is interrupted by a signal
or to retry select()+sock_func() on false positive (see above) */
diff --git a/Objects/object.c b/Objects/object.c
index 4e900d8e79d91a..51b6016b9c191c 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -3073,14 +3073,14 @@ _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt)
}
int PyRefTracer_SetTracer(PyRefTracer tracer, void *data) {
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
_PyRuntime.ref_tracer.tracer_func = tracer;
_PyRuntime.ref_tracer.tracer_data = data;
return 0;
}
PyRefTracer PyRefTracer_GetTracer(void** data) {
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
if (data != NULL) {
*data = _PyRuntime.ref_tracer.tracer_data;
}
diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c
index b103deb01ca712..5688049b024696 100644
--- a/Objects/obmalloc.c
+++ b/Objects/obmalloc.c
@@ -2909,7 +2909,8 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
static inline void
_PyMem_DebugCheckGIL(const char *func)
{
- if (!PyGILState_Check()) {
+ PyThreadState *tstate = _PyThreadState_GET();
+ if (tstate == NULL) {
#ifndef Py_GIL_DISABLED
_Py_FatalErrorFunc(func,
"Python memory allocator called "
diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c
index 1f811e72406130..416eec01052224 100644
--- a/Python/ceval_gil.c
+++ b/Python/ceval_gil.c
@@ -995,7 +995,7 @@ _Py_unset_eval_breaker_bit_all(PyInterpreterState *interp, uintptr_t bit)
void
_Py_FinishPendingCalls(PyThreadState *tstate)
{
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
assert(_PyThreadState_CheckConsistency(tstate));
struct _pending_calls *pending = &tstate->interp->ceval.pending;
@@ -1056,7 +1056,7 @@ _PyEval_MakePendingCalls(PyThreadState *tstate)
int
Py_MakePendingCalls(void)
{
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
PyThreadState *tstate = _PyThreadState_GET();
assert(_PyThreadState_CheckConsistency(tstate));
diff --git a/Python/errors.c b/Python/errors.c
index b6ac2f767a283b..9c7b771133dcf4 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -314,8 +314,8 @@ _PyErr_SetLocaleString(PyObject *exception, const char *string)
PyObject* _Py_HOT_FUNCTION
PyErr_Occurred(void)
{
- /* The caller must hold the GIL. */
- assert(PyGILState_Check());
+ /* The caller must hold a thread state. */
+ _Py_AssertHoldsTstate();
PyThreadState *tstate = _PyThreadState_GET();
return _PyErr_Occurred(tstate);
diff --git a/Python/fileutils.c b/Python/fileutils.c
index 6bc3a44c3c1313..72804c39220591 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -1,6 +1,7 @@
#include "Python.h"
#include "pycore_fileutils.h" // fileutils definitions
#include "pycore_runtime.h" // _PyRuntime
+#include "pycore_pystate.h" // _Py_AssertHoldsTstate()
#include "osdefs.h" // SEP
#include <stdlib.h> // mbstowcs()
@@ -1311,7 +1312,7 @@ _Py_fstat(int fd, struct _Py_stat_struct *status)
{
int res;
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
Py_BEGIN_ALLOW_THREADS
res = _Py_fstat_noraise(fd, status);
@@ -1691,7 +1692,7 @@ int
_Py_open(const char *pathname, int flags)
{
/* _Py_open() must be called with the GIL held. */
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
return _Py_open_impl(pathname, flags, 1);
}
@@ -1766,7 +1767,7 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode)
FILE*
Py_fopen(PyObject *path, const char *mode)
{
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
if (PySys_Audit("open", "Osi", path, mode, 0) < 0) {
return NULL;
@@ -1881,7 +1882,7 @@ _Py_read(int fd, void *buf, size_t count)
int err;
int async_err = 0;
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
/* _Py_read() must not be called with an exception set, otherwise the
* caller may think that read() was interrupted by a signal and the signal
@@ -2047,7 +2048,7 @@ _Py_write_impl(int fd, const void *buf, size_t count, int gil_held)
Py_ssize_t
_Py_write(int fd, const void *buf, size_t count)
{
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
/* _Py_write() must not be called with an exception set, otherwise the
* caller may think that write() was interrupted by a signal and the signal
@@ -2675,7 +2676,7 @@ _Py_dup(int fd)
HANDLE handle;
#endif
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
#ifdef MS_WINDOWS
handle = _Py_get_osfhandle(fd);
diff --git a/Python/legacy_tracing.c b/Python/legacy_tracing.c
index 45af275f1f6dce..97634f9183c7d5 100644
--- a/Python/legacy_tracing.c
+++ b/Python/legacy_tracing.c
@@ -491,8 +491,8 @@ int
_PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
{
assert(is_tstate_valid(tstate));
- /* The caller must hold the GIL */
- assert(PyGILState_Check());
+ /* The caller must hold a thread state */
+ _Py_AssertHoldsTstate();
/* Call _PySys_Audit() in the context of the current thread state,
even if tstate is not the current thread state. */
@@ -586,8 +586,8 @@ int
_PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
{
assert(is_tstate_valid(tstate));
- /* The caller must hold the GIL */
- assert(PyGILState_Check());
+ /* The caller must hold a thread state */
+ _Py_AssertHoldsTstate();
/* Call _PySys_Audit() in the context of the current thread state,
even if tstate is not the current thread state. */
diff --git a/Python/pystate.c b/Python/pystate.c
index c546b7c3a9f10e..52703b048d6022 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -2897,7 +2897,6 @@ _PyInterpreterState_GetConfigCopy(PyConfig *config)
const PyConfig*
_Py_GetConfig(void)
{
- assert(PyGILState_Check());
PyThreadState *tstate = current_fast_get();
_Py_EnsureTstateNotNULL(tstate);
return _PyInterpreterState_GetConfig(tstate->interp);
diff --git a/Python/pytime.c b/Python/pytime.c
index 2b37cd991ef4e4..c039fc98ce4bde 100644
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -1,5 +1,6 @@
#include "Python.h"
#include "pycore_time.h" // PyTime_t
+#include "pycore_pystate.h" // _Py_AssertHoldsTstate()
#include <time.h> // gmtime_r()
#ifdef HAVE_SYS_TIME_H
@@ -897,14 +898,14 @@ _PyTime_AsTimespec(PyTime_t t, struct timespec *ts)
#endif
-// N.B. If raise_exc=0, this may be called without the GIL.
+// N.B. If raise_exc=0, this may be called without a thread state.
static int
py_get_system_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
{
assert(info == NULL || raise_exc);
if (raise_exc) {
- // raise_exc requires to hold the GIL
- assert(PyGILState_Check());
+ // raise_exc requires to hold a thread state
+ _Py_AssertHoldsTstate();
}
#ifdef MS_WINDOWS
@@ -1142,14 +1143,14 @@ py_mach_timebase_info(_PyTimeFraction *base, int raise_exc)
#endif
-// N.B. If raise_exc=0, this may be called without the GIL.
+// N.B. If raise_exc=0, this may be called without a thread state.
static int
py_get_monotonic_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
{
assert(info == NULL || raise_exc);
if (raise_exc) {
- // raise_exc requires to hold the GIL
- assert(PyGILState_Check());
+ // raise_exc requires to hold a thread state
+ _Py_AssertHoldsTstate();
}
#if defined(MS_WINDOWS)
diff --git a/Python/tracemalloc.c b/Python/tracemalloc.c
index 919c564ee72967..a9f45e5ead1a11 100644
--- a/Python/tracemalloc.c
+++ b/Python/tracemalloc.c
@@ -367,7 +367,7 @@ traceback_new(void)
traceback_t *traceback;
_Py_hashtable_entry_t *entry;
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
/* get frames */
traceback = tracemalloc_traceback;
@@ -749,7 +749,7 @@ static void
tracemalloc_clear_traces_unlocked(void)
{
// Clearing tracemalloc_filenames requires the GIL to call Py_DECREF()
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
set_reentrant(1);
@@ -1302,7 +1302,7 @@ PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
void
_PyTraceMalloc_Fini(void)
{
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
tracemalloc_deinit();
}
@@ -1323,7 +1323,7 @@ _PyTraceMalloc_TraceRef(PyObject *op, PyRefTracerEvent event,
return 0;
}
- assert(PyGILState_Check());
+ _Py_AssertHoldsTstate();
TABLES_LOCK();
if (!tracemalloc_config.tracing) {
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/c6b570e5e3b214d2038645c5fa7806e0fb…
commit: c6b570e5e3b214d2038645c5fa7806e0fb3f7dcd
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: kumaraditya303 <kumaraditya(a)python.org>
date: 2025-01-20T17:02:39+05:30
summary:
gh-71339: Use new assertion methods in `test_asyncio` (#129051)
files:
M Lib/test/test_asyncio/test_base_events.py
M Lib/test/test_asyncio/test_events.py
M Lib/test/test_asyncio/test_futures.py
M Lib/test/test_asyncio/test_locks.py
M Lib/test/test_asyncio/test_protocols.py
M Lib/test/test_asyncio/test_queues.py
M Lib/test/test_asyncio/test_sock_lowlevel.py
M Lib/test/test_asyncio/test_streams.py
M Lib/test/test_asyncio/test_tasks.py
M Lib/test/test_asyncio/test_windows_utils.py
diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py
index 1e063c1352ecb9..102c9be0ecf031 100644
--- a/Lib/test/test_asyncio/test_base_events.py
+++ b/Lib/test/test_asyncio/test_base_events.py
@@ -1345,7 +1345,7 @@ def getaddrinfo_task(*args, **kwds):
with self.assertRaises(OSError) as cm:
self.loop.run_until_complete(coro)
- self.assertTrue(str(cm.exception).startswith('Multiple exceptions: '))
+ self.assertStartsWith(str(cm.exception), 'Multiple exceptions: ')
self.assertTrue(m_socket.socket.return_value.close.called)
coro = self.loop.create_connection(
diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py
index ed75b909317357..ada049e9c7d387 100644
--- a/Lib/test/test_asyncio/test_events.py
+++ b/Lib/test/test_asyncio/test_events.py
@@ -2184,7 +2184,7 @@ def test_subprocess_stderr(self):
transp.close()
self.assertEqual(b'OUT:test', proto.data[1])
- self.assertTrue(proto.data[2].startswith(b'ERR:test'), proto.data[2])
+ self.assertStartsWith(proto.data[2], b'ERR:test')
self.assertEqual(0, proto.returncode)
@support.requires_subprocess()
@@ -2206,8 +2206,7 @@ def test_subprocess_stderr_redirect_to_stdout(self):
stdin.write(b'test')
self.loop.run_until_complete(proto.completed)
- self.assertTrue(proto.data[1].startswith(b'OUT:testERR:test'),
- proto.data[1])
+ self.assertStartsWith(proto.data[1], b'OUT:testERR:test')
self.assertEqual(b'', proto.data[2])
transp.close()
diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py
index 84b44011b9a844..01d6230e6dd9a3 100644
--- a/Lib/test/test_asyncio/test_futures.py
+++ b/Lib/test/test_asyncio/test_futures.py
@@ -242,7 +242,7 @@ def test_uninitialized(self):
def test_future_cancel_message_getter(self):
f = self._new_future(loop=self.loop)
- self.assertTrue(hasattr(f, '_cancel_message'))
+ self.assertHasAttr(f, '_cancel_message')
self.assertEqual(f._cancel_message, None)
f.cancel('my message')
diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py
index aabfcd418829b2..3bb3e5c4ca0658 100644
--- a/Lib/test/test_asyncio/test_locks.py
+++ b/Lib/test/test_asyncio/test_locks.py
@@ -27,11 +27,11 @@ class LockTests(unittest.IsolatedAsyncioTestCase):
async def test_repr(self):
lock = asyncio.Lock()
- self.assertTrue(repr(lock).endswith('[unlocked]>'))
+ self.assertEndsWith(repr(lock), '[unlocked]>')
self.assertTrue(RGX_REPR.match(repr(lock)))
await lock.acquire()
- self.assertTrue(repr(lock).endswith('[locked]>'))
+ self.assertEndsWith(repr(lock), '[locked]>')
self.assertTrue(RGX_REPR.match(repr(lock)))
async def test_lock(self):
@@ -286,12 +286,12 @@ class EventTests(unittest.IsolatedAsyncioTestCase):
def test_repr(self):
ev = asyncio.Event()
- self.assertTrue(repr(ev).endswith('[unset]>'))
+ self.assertEndsWith(repr(ev), '[unset]>')
match = RGX_REPR.match(repr(ev))
self.assertEqual(match.group('extras'), 'unset')
ev.set()
- self.assertTrue(repr(ev).endswith('[set]>'))
+ self.assertEndsWith(repr(ev), '[set]>')
self.assertTrue(RGX_REPR.match(repr(ev)))
ev._waiters.append(mock.Mock())
@@ -916,11 +916,11 @@ def test_initial_value_zero(self):
async def test_repr(self):
sem = asyncio.Semaphore()
- self.assertTrue(repr(sem).endswith('[unlocked, value:1]>'))
+ self.assertEndsWith(repr(sem), '[unlocked, value:1]>')
self.assertTrue(RGX_REPR.match(repr(sem)))
await sem.acquire()
- self.assertTrue(repr(sem).endswith('[locked]>'))
+ self.assertEndsWith(repr(sem), '[locked]>')
self.assertTrue('waiters' not in repr(sem))
self.assertTrue(RGX_REPR.match(repr(sem)))
diff --git a/Lib/test/test_asyncio/test_protocols.py b/Lib/test/test_asyncio/test_protocols.py
index a8627b5b5b87f2..4484a031988533 100644
--- a/Lib/test/test_asyncio/test_protocols.py
+++ b/Lib/test/test_asyncio/test_protocols.py
@@ -19,7 +19,7 @@ def test_base_protocol(self):
self.assertIsNone(p.connection_lost(f))
self.assertIsNone(p.pause_writing())
self.assertIsNone(p.resume_writing())
- self.assertFalse(hasattr(p, '__dict__'))
+ self.assertNotHasAttr(p, '__dict__')
def test_protocol(self):
f = mock.Mock()
@@ -30,7 +30,7 @@ def test_protocol(self):
self.assertIsNone(p.eof_received())
self.assertIsNone(p.pause_writing())
self.assertIsNone(p.resume_writing())
- self.assertFalse(hasattr(p, '__dict__'))
+ self.assertNotHasAttr(p, '__dict__')
def test_buffered_protocol(self):
f = mock.Mock()
@@ -41,7 +41,7 @@ def test_buffered_protocol(self):
self.assertIsNone(p.buffer_updated(150))
self.assertIsNone(p.pause_writing())
self.assertIsNone(p.resume_writing())
- self.assertFalse(hasattr(p, '__dict__'))
+ self.assertNotHasAttr(p, '__dict__')
def test_datagram_protocol(self):
f = mock.Mock()
@@ -50,7 +50,7 @@ def test_datagram_protocol(self):
self.assertIsNone(dp.connection_lost(f))
self.assertIsNone(dp.error_received(f))
self.assertIsNone(dp.datagram_received(f, f))
- self.assertFalse(hasattr(dp, '__dict__'))
+ self.assertNotHasAttr(dp, '__dict__')
def test_subprocess_protocol(self):
f = mock.Mock()
@@ -60,7 +60,7 @@ def test_subprocess_protocol(self):
self.assertIsNone(sp.pipe_data_received(1, f))
self.assertIsNone(sp.pipe_connection_lost(1, f))
self.assertIsNone(sp.process_exited())
- self.assertFalse(hasattr(sp, '__dict__'))
+ self.assertNotHasAttr(sp, '__dict__')
if __name__ == '__main__':
diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py
index 1a8d604faea1fd..090b9774c2289f 100644
--- a/Lib/test/test_asyncio/test_queues.py
+++ b/Lib/test/test_asyncio/test_queues.py
@@ -18,7 +18,7 @@ async def _test_repr_or_str(self, fn, expect_id):
appear in fn(Queue()).
"""
q = asyncio.Queue()
- self.assertTrue(fn(q).startswith('<Queue'), fn(q))
+ self.assertStartsWith(fn(q), '<Queue')
id_is_present = hex(id(q)) in fn(q)
self.assertEqual(expect_id, id_is_present)
diff --git a/Lib/test/test_asyncio/test_sock_lowlevel.py b/Lib/test/test_asyncio/test_sock_lowlevel.py
index 5b1e5143820cad..4f7b9a1dda6b78 100644
--- a/Lib/test/test_asyncio/test_sock_lowlevel.py
+++ b/Lib/test/test_asyncio/test_sock_lowlevel.py
@@ -110,7 +110,7 @@ def _basetest_sock_client_ops(self, httpd, sock):
self.loop.run_until_complete(
self.loop.sock_recv(sock, 1024))
sock.close()
- self.assertTrue(data.startswith(b'HTTP/1.0 200 OK'))
+ self.assertStartsWith(data, b'HTTP/1.0 200 OK')
def _basetest_sock_recv_into(self, httpd, sock):
# same as _basetest_sock_client_ops, but using sock_recv_into
@@ -127,7 +127,7 @@ def _basetest_sock_recv_into(self, httpd, sock):
self.loop.run_until_complete(
self.loop.sock_recv_into(sock, buf[nbytes:]))
sock.close()
- self.assertTrue(data.startswith(b'HTTP/1.0 200 OK'))
+ self.assertStartsWith(data, b'HTTP/1.0 200 OK')
def test_sock_client_ops(self):
with test_utils.run_test_server() as httpd:
@@ -150,7 +150,7 @@ async def _basetest_sock_recv_racing(self, httpd, sock):
# consume data
await self.loop.sock_recv(sock, 1024)
- self.assertTrue(data.startswith(b'HTTP/1.0 200 OK'))
+ self.assertStartsWith(data, b'HTTP/1.0 200 OK')
async def _basetest_sock_recv_into_racing(self, httpd, sock):
sock.setblocking(False)
@@ -168,7 +168,7 @@ async def _basetest_sock_recv_into_racing(self, httpd, sock):
nbytes = await self.loop.sock_recv_into(sock, buf[:1024])
# consume data
await self.loop.sock_recv_into(sock, buf[nbytes:])
- self.assertTrue(data.startswith(b'HTTP/1.0 200 OK'))
+ self.assertStartsWith(data, b'HTTP/1.0 200 OK')
await task
@@ -217,7 +217,7 @@ async def recv_all():
sock.shutdown(socket.SHUT_WR)
data = await task
# ProactorEventLoop could deliver hello, so endswith is necessary
- self.assertTrue(data.endswith(b'world'))
+ self.assertEndsWith(data, b'world')
# After the first connect attempt before the listener is ready,
# the socket needs time to "recover" to make the next connect call.
@@ -298,7 +298,7 @@ async def _basetest_huge_content(self, address):
data = await self.loop.sock_recv(sock, DATA_SIZE)
# HTTP headers size is less than MTU,
# they are sent by the first packet always
- self.assertTrue(data.startswith(b'HTTP/1.0 200 OK'))
+ self.assertStartsWith(data, b'HTTP/1.0 200 OK')
while data.find(b'\r\n\r\n') == -1:
data += await self.loop.sock_recv(sock, DATA_SIZE)
# Strip headers
@@ -351,7 +351,7 @@ async def _basetest_huge_content_recvinto(self, address):
data = bytes(buf[:nbytes])
# HTTP headers size is less than MTU,
# they are sent by the first packet always
- self.assertTrue(data.startswith(b'HTTP/1.0 200 OK'))
+ self.assertStartsWith(data, b'HTTP/1.0 200 OK')
while data.find(b'\r\n\r\n') == -1:
nbytes = await self.loop.sock_recv_into(sock, buf)
data = bytes(buf[:nbytes])
diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py
index 047ada8c5d23df..673c6b46c647f3 100644
--- a/Lib/test/test_asyncio/test_streams.py
+++ b/Lib/test/test_asyncio/test_streams.py
@@ -50,7 +50,7 @@ def _basetest_open_connection(self, open_connection_fut):
self.assertEqual(data, b'HTTP/1.0 200 OK\r\n')
f = reader.read()
data = self.loop.run_until_complete(f)
- self.assertTrue(data.endswith(b'\r\n\r\nTest message'))
+ self.assertEndsWith(data, b'\r\n\r\nTest message')
writer.close()
self.assertEqual(messages, [])
@@ -75,7 +75,7 @@ def _basetest_open_connection_no_loop_ssl(self, open_connection_fut):
writer.write(b'GET / HTTP/1.0\r\n\r\n')
f = reader.read()
data = self.loop.run_until_complete(f)
- self.assertTrue(data.endswith(b'\r\n\r\nTest message'))
+ self.assertEndsWith(data, b'\r\n\r\nTest message')
writer.close()
self.assertEqual(messages, [])
@@ -1002,7 +1002,7 @@ def test_wait_closed_on_close(self):
self.assertEqual(data, b'HTTP/1.0 200 OK\r\n')
f = rd.read()
data = self.loop.run_until_complete(f)
- self.assertTrue(data.endswith(b'\r\n\r\nTest message'))
+ self.assertEndsWith(data, b'\r\n\r\nTest message')
self.assertFalse(wr.is_closing())
wr.close()
self.assertTrue(wr.is_closing())
@@ -1028,7 +1028,7 @@ async def inner(httpd):
data = await rd.readline()
self.assertEqual(data, b'HTTP/1.0 200 OK\r\n')
data = await rd.read()
- self.assertTrue(data.endswith(b'\r\n\r\nTest message'))
+ self.assertEndsWith(data, b'\r\n\r\nTest message')
wr.close()
await wr.wait_closed()
@@ -1048,7 +1048,7 @@ async def inner(httpd):
data = await rd.readline()
self.assertEqual(data, b'HTTP/1.0 200 OK\r\n')
data = await rd.read()
- self.assertTrue(data.endswith(b'\r\n\r\nTest message'))
+ self.assertEndsWith(data, b'\r\n\r\nTest message')
wr.close()
with self.assertRaises(ConnectionResetError):
wr.write(b'data')
@@ -1089,12 +1089,12 @@ async def inner(httpd):
data = await rd.readline()
self.assertEqual(data, b'HTTP/1.0 200 OK\r\n')
data = await rd.read()
- self.assertTrue(data.endswith(b'\r\n\r\nTest message'))
+ self.assertEndsWith(data, b'\r\n\r\nTest message')
with self.assertWarns(ResourceWarning) as cm:
del wr
gc.collect()
self.assertEqual(len(cm.warnings), 1)
- self.assertTrue(str(cm.warnings[0].message).startswith("unclosed <StreamWriter"))
+ self.assertStartsWith(str(cm.warnings[0].message), "unclosed <StreamWriter")
messages = []
self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx))
@@ -1112,7 +1112,7 @@ async def inner(httpd):
data = await rd.readline()
self.assertEqual(data, b'HTTP/1.0 200 OK\r\n')
data = await rd.read()
- self.assertTrue(data.endswith(b'\r\n\r\nTest message'))
+ self.assertEndsWith(data, b'\r\n\r\nTest message')
# Make "loop is closed" occur first before "del wr" for this test.
self.loop.stop()
@@ -1144,7 +1144,7 @@ async def inner(rd, wr):
del wr
gc.collect()
self.assertEqual(len(cm.warnings), 1)
- self.assertTrue(str(cm.warnings[0].message).startswith("unclosed <StreamWriter"))
+ self.assertStartsWith(str(cm.warnings[0].message), "unclosed <StreamWriter")
async def outer():
srv = await asyncio.start_server(inner, socket_helper.HOSTv4, 0)
diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py
index b5363226ad79f4..7a052817766a07 100644
--- a/Lib/test/test_asyncio/test_tasks.py
+++ b/Lib/test/test_asyncio/test_tasks.py
@@ -110,7 +110,7 @@ def test_task_cancel_message_getter(self):
async def coro():
pass
t = self.new_task(self.loop, coro())
- self.assertTrue(hasattr(t, '_cancel_message'))
+ self.assertHasAttr(t, '_cancel_message')
self.assertEqual(t._cancel_message, None)
t.cancel('my message')
@@ -3131,7 +3131,7 @@ def new_task(self, coro):
class GenericTaskTests(test_utils.TestCase):
def test_future_subclass(self):
- self.assertTrue(issubclass(asyncio.Task, asyncio.Future))
+ self.assertIsSubclass(asyncio.Task, asyncio.Future)
@support.cpython_only
def test_asyncio_module_compiled(self):
diff --git a/Lib/test/test_asyncio/test_windows_utils.py b/Lib/test/test_asyncio/test_windows_utils.py
index be70720707cea7..a6b207567c4f00 100644
--- a/Lib/test/test_asyncio/test_windows_utils.py
+++ b/Lib/test/test_asyncio/test_windows_utils.py
@@ -121,8 +121,8 @@ def test_popen(self):
self.assertGreater(len(out), 0)
self.assertGreater(len(err), 0)
# allow for partial reads...
- self.assertTrue(msg.upper().rstrip().startswith(out))
- self.assertTrue(b"stderr".startswith(err))
+ self.assertStartsWith(msg.upper().rstrip(), out)
+ self.assertStartsWith(b"stderr", err)
# The context manager calls wait() and closes resources
with p:
1
0
gh-128595: Default to stdout isatty for colour detection instead of stderr (#128498)
by hugovk Jan. 20, 2025
by hugovk Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/6f167d71347de6717d9f6b64026e21f23d…
commit: 6f167d71347de6717d9f6b64026e21f23d41ef0b
branch: main
author: Hugo van Kemenade <1324225+hugovk(a)users.noreply.github.com>
committer: hugovk <1324225+hugovk(a)users.noreply.github.com>
date: 2025-01-20T12:52:42+02:00
summary:
gh-128595: Default to stdout isatty for colour detection instead of stderr (#128498)
Co-authored-by: Serhiy Storchaka <storchaka(a)gmail.com>
Co-authored-by: Victor Stinner <vstinner(a)python.org>
files:
A Misc/NEWS.d/next/Library/2025-01-07-21-48-32.gh-issue-128498.n6jtlW.rst
M Lib/_colorize.py
M Lib/doctest.py
M Lib/test/libregrtest/single.py
M Lib/test/support/__init__.py
M Lib/traceback.py
M Lib/unittest/result.py
M Lib/unittest/runner.py
diff --git a/Lib/_colorize.py b/Lib/_colorize.py
index f609901887a26b..bab2e599b2c810 100644
--- a/Lib/_colorize.py
+++ b/Lib/_colorize.py
@@ -26,14 +26,17 @@ class ANSIColors:
setattr(NoColors, attr, "")
-def get_colors(colorize: bool = False) -> ANSIColors:
- if colorize or can_colorize():
+def get_colors(colorize: bool = False, *, file=None) -> ANSIColors:
+ if colorize or can_colorize(file=file):
return ANSIColors()
else:
return NoColors
-def can_colorize() -> bool:
+def can_colorize(*, file=None) -> bool:
+ if file is None:
+ file = sys.stdout
+
if not sys.flags.ignore_environment:
if os.environ.get("PYTHON_COLORS") == "0":
return False
@@ -49,7 +52,7 @@ def can_colorize() -> bool:
if os.environ.get("TERM") == "dumb":
return False
- if not hasattr(sys.stderr, "fileno"):
+ if not hasattr(file, "fileno"):
return False
if sys.platform == "win32":
@@ -62,6 +65,6 @@ def can_colorize() -> bool:
return False
try:
- return os.isatty(sys.stderr.fileno())
+ return os.isatty(file.fileno())
except io.UnsupportedOperation:
- return sys.stderr.isatty()
+ return file.isatty()
diff --git a/Lib/doctest.py b/Lib/doctest.py
index bb281fc483c41c..e02e73ed722f7e 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -1558,7 +1558,7 @@ def out(s):
save_displayhook = sys.displayhook
sys.displayhook = sys.__displayhook__
saved_can_colorize = _colorize.can_colorize
- _colorize.can_colorize = lambda: False
+ _colorize.can_colorize = lambda *args, **kwargs: False
color_variables = {"PYTHON_COLORS": None, "FORCE_COLOR": None}
for key in color_variables:
color_variables[key] = os.environ.pop(key, None)
diff --git a/Lib/test/libregrtest/single.py b/Lib/test/libregrtest/single.py
index 0e174f82abed28..54df688bbc470e 100644
--- a/Lib/test/libregrtest/single.py
+++ b/Lib/test/libregrtest/single.py
@@ -162,8 +162,8 @@ def test_func():
def _runtest_env_changed_exc(result: TestResult, runtests: RunTests,
display_failure: bool = True) -> None:
# Handle exceptions, detect environment changes.
- ansi = get_colors()
- red, reset, yellow = ansi.RED, ansi.RESET, ansi.YELLOW
+ stdout = get_colors(file=sys.stdout)
+ stderr = get_colors(file=sys.stderr)
# Reset the environment_altered flag to detect if a test altered
# the environment
@@ -184,18 +184,24 @@ def _runtest_env_changed_exc(result: TestResult, runtests: RunTests,
_load_run_test(result, runtests)
except support.ResourceDenied as exc:
if not quiet and not pgo:
- print(f"{yellow}{test_name} skipped -- {exc}{reset}", flush=True)
+ print(
+ f"{stdout.YELLOW}{test_name} skipped -- {exc}{stdout.RESET}",
+ flush=True,
+ )
result.state = State.RESOURCE_DENIED
return
except unittest.SkipTest as exc:
if not quiet and not pgo:
- print(f"{yellow}{test_name} skipped -- {exc}{reset}", flush=True)
+ print(
+ f"{stdout.YELLOW}{test_name} skipped -- {exc}{stdout.RESET}",
+ flush=True,
+ )
result.state = State.SKIPPED
return
except support.TestFailedWithDetails as exc:
- msg = f"{red}test {test_name} failed{reset}"
+ msg = f"{stderr.RED}test {test_name} failed{stderr.RESET}"
if display_failure:
- msg = f"{red}{msg} -- {exc}{reset}"
+ msg = f"{stderr.RED}{msg} -- {exc}{stderr.RESET}"
print(msg, file=sys.stderr, flush=True)
result.state = State.FAILED
result.errors = exc.errors
@@ -203,9 +209,9 @@ def _runtest_env_changed_exc(result: TestResult, runtests: RunTests,
result.stats = exc.stats
return
except support.TestFailed as exc:
- msg = f"{red}test {test_name} failed{reset}"
+ msg = f"{stderr.RED}test {test_name} failed{stderr.RESET}"
if display_failure:
- msg = f"{red}{msg} -- {exc}{reset}"
+ msg = f"{stderr.RED}{msg} -- {exc}{stderr.RESET}"
print(msg, file=sys.stderr, flush=True)
result.state = State.FAILED
result.stats = exc.stats
@@ -220,8 +226,11 @@ def _runtest_env_changed_exc(result: TestResult, runtests: RunTests,
except:
if not pgo:
msg = traceback.format_exc()
- print(f"{red}test {test_name} crashed -- {msg}{reset}",
- file=sys.stderr, flush=True)
+ print(
+ f"{stderr.RED}test {test_name} crashed -- {msg}{stderr.RESET}",
+ file=sys.stderr,
+ flush=True,
+ )
result.state = State.UNCAUGHT_EXC
return
@@ -303,7 +312,7 @@ def run_single_test(test_name: TestName, runtests: RunTests) -> TestResult:
If runtests.use_junit, xml_data is a list containing each generated
testsuite element.
"""
- ansi = get_colors()
+ ansi = get_colors(file=sys.stderr)
red, reset, yellow = ansi.BOLD_RED, ansi.RESET, ansi.YELLOW
start_time = time.perf_counter()
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index ee9520a8838625..e05e91babc2499 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -2839,7 +2839,7 @@ def no_color():
from .os_helper import EnvironmentVarGuard
with (
- swap_attr(_colorize, "can_colorize", lambda: False),
+ swap_attr(_colorize, "can_colorize", lambda file=None: False),
EnvironmentVarGuard() as env,
):
for var in {"FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS"}:
diff --git a/Lib/traceback.py b/Lib/traceback.py
index 6367c00e4d4b86..3ed06af15a0a89 100644
--- a/Lib/traceback.py
+++ b/Lib/traceback.py
@@ -135,7 +135,7 @@ def print_exception(exc, /, value=_sentinel, tb=_sentinel, limit=None, \
def _print_exception_bltin(exc, /):
file = sys.stderr if sys.stderr is not None else sys.__stderr__
- colorize = _colorize.can_colorize()
+ colorize = _colorize.can_colorize(file=file)
return print_exception(exc, limit=BUILTIN_EXCEPTION_LIMIT, file=file, colorize=colorize)
diff --git a/Lib/unittest/result.py b/Lib/unittest/result.py
index 97262735aa8311..b8ea396db6772e 100644
--- a/Lib/unittest/result.py
+++ b/Lib/unittest/result.py
@@ -191,7 +191,8 @@ def _exc_info_to_string(self, err, test):
capture_locals=self.tb_locals, compact=True)
from _colorize import can_colorize
- msgLines = list(tb_e.format(colorize=can_colorize()))
+ colorize = hasattr(self, "stream") and can_colorize(file=self.stream)
+ msgLines = list(tb_e.format(colorize=colorize))
if self.buffer:
output = sys.stdout.getvalue()
diff --git a/Lib/unittest/runner.py b/Lib/unittest/runner.py
index d60c295a1eddf7..eb0234a2617680 100644
--- a/Lib/unittest/runner.py
+++ b/Lib/unittest/runner.py
@@ -45,7 +45,7 @@ def __init__(self, stream, descriptions, verbosity, *, durations=None):
self.showAll = verbosity > 1
self.dots = verbosity == 1
self.descriptions = descriptions
- self._ansi = get_colors()
+ self._ansi = get_colors(file=stream)
self._newline = True
self.durations = durations
@@ -286,7 +286,7 @@ def run(self, test):
expected_fails, unexpected_successes, skipped = results
infos = []
- ansi = get_colors()
+ ansi = get_colors(file=self.stream)
bold_red = ansi.BOLD_RED
green = ansi.GREEN
red = ansi.RED
diff --git a/Misc/NEWS.d/next/Library/2025-01-07-21-48-32.gh-issue-128498.n6jtlW.rst b/Misc/NEWS.d/next/Library/2025-01-07-21-48-32.gh-issue-128498.n6jtlW.rst
new file mode 100644
index 00000000000000..9a241e37c20a44
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-01-07-21-48-32.gh-issue-128498.n6jtlW.rst
@@ -0,0 +1,2 @@
+Default to stdout isatty for color detection instead of stderr. Patch by
+Hugo van Kemenade.
1
0
https://github.com/python/cpython/commit/a42915979796565635dcfcd45d2b62b3e5…
commit: a42915979796565635dcfcd45d2b62b3e5e46eba
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-20T11:42:04+01:00
summary:
Reorganize the PyInitConfig documentation (#129047)
Document the new PyInitConfig API before the old PyConfig API.
files:
M Doc/c-api/init_config.rst
diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst
index 85566631ca1676..a549d4c55fc43d 100644
--- a/Doc/c-api/init_config.rst
+++ b/Doc/c-api/init_config.rst
@@ -6,28 +6,15 @@
Python Initialization Configuration
***********************************
-.. _pyconfig_api:
-
-PyConfig C API
-==============
-.. versionadded:: 3.8
-
-Python can be initialized with :c:func:`Py_InitializeFromConfig` and the
-:c:type:`PyConfig` structure. It can be preinitialized with
-:c:func:`Py_PreInitialize` and the :c:type:`PyPreConfig` structure.
+.. _pyinitconfig_api:
-There are two kinds of configuration:
+PyInitConfig C API
+==================
-* The :ref:`Python Configuration <init-python-config>` can be used to build a
- customized Python which behaves as the regular Python. For example,
- environment variables and command line arguments are used to configure
- Python.
+.. versionadded:: 3.14
-* The :ref:`Isolated Configuration <init-isolated-conf>` can be used to embed
- Python into an application. It isolates Python from the system. For example,
- environment variables are ignored, the LC_CTYPE locale is left unchanged and
- no signal handler is registered.
+Python can be initialized with :c:func:`Py_InitializeFromInitConfig`.
The :c:func:`Py_RunMain` function can be used to write a customized Python
program.
@@ -35,1906 +22,1920 @@ program.
See also :ref:`Initialization, Finalization, and Threads <initialization>`.
.. seealso::
- :pep:`587` "Python Initialization Configuration".
+ :pep:`741` "Python Configuration C API".
Example
-------
-Example of customized Python always running in isolated mode::
-
- int main(int argc, char **argv)
- {
- PyStatus status;
+Example of customized Python always running with the :ref:`Python Development
+Mode <devmode>` enabled; return ``-1`` on error:
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
- config.isolated = 1;
+.. code-block:: c
- /* Decode command line arguments.
- Implicitly preinitialize Python (in isolated mode). */
- status = PyConfig_SetBytesArgv(&config, argc, argv);
- if (PyStatus_Exception(status)) {
- goto exception;
+ int init_python(void)
+ {
+ PyInitConfig *config = PyInitConfig_Create();
+ if (config == NULL) {
+ printf("PYTHON INIT ERROR: memory allocation failed\n");
+ return -1;
}
- status = Py_InitializeFromConfig(&config);
- if (PyStatus_Exception(status)) {
- goto exception;
+ // Enable the Python Development Mode
+ if (PyInitConfig_SetInt(config, "dev_mode", 1) < 0) {
+ goto error;
}
- PyConfig_Clear(&config);
- return Py_RunMain();
+ // Initialize Python with the configuration
+ if (Py_InitializeFromInitConfig(config) < 0) {
+ goto error;
+ }
+ PyInitConfig_Free(config);
+ return 0;
- exception:
- PyConfig_Clear(&config);
- if (PyStatus_IsExit(status)) {
- return status.exitcode;
+ error:
+ {
+ // Display the error message.
+ //
+ // This uncommon braces style is used, because you cannot make
+ // goto targets point to variable declarations.
+ const char *err_msg;
+ (void)PyInitConfig_GetError(config, &err_msg);
+ printf("PYTHON INIT ERROR: %s\n", err_msg);
+ PyInitConfig_Free(config);
+ return -1;
}
- /* Display the error message and exit the process with
- non-zero exit code */
- Py_ExitStatusException(status);
}
+Create Config
+-------------
-PyWideStringList
-----------------
+.. c:struct:: PyInitConfig
-.. c:type:: PyWideStringList
+ Opaque structure to configure the Python initialization.
- List of ``wchar_t*`` strings.
- If *length* is non-zero, *items* must be non-``NULL`` and all strings must be
- non-``NULL``.
+.. c:function:: PyInitConfig* PyInitConfig_Create(void)
- .. c:namespace:: NULL
+ Create a new initialization configuration using :ref:`Isolated Configuration
+ <init-isolated-conf>` default values.
- Methods:
+ It must be freed by :c:func:`PyInitConfig_Free`.
- .. c:function:: PyStatus PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
+ Return ``NULL`` on memory allocation failure.
- Append *item* to *list*.
- Python must be preinitialized to call this function.
+.. c:function:: void PyInitConfig_Free(PyInitConfig *config)
- .. c:function:: PyStatus PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item)
+ Free memory of the initialization configuration *config*.
- Insert *item* into *list* at *index*.
+ If *config* is ``NULL``, no operation is performed.
- If *index* is greater than or equal to *list* length, append *item* to
- *list*.
- *index* must be greater than or equal to ``0``.
+Error Handling
+--------------
- Python must be preinitialized to call this function.
+.. c:function:: int PyInitConfig_GetError(PyInitConfig* config, const char **err_msg)
- .. c:namespace:: PyWideStringList
+ Get the *config* error message.
- Structure fields:
+ * Set *\*err_msg* and return ``1`` if an error is set.
+ * Set *\*err_msg* to ``NULL`` and return ``0`` otherwise.
- .. c:member:: Py_ssize_t length
+ An error message is an UTF-8 encoded string.
- List length.
+ If *config* has an exit code, format the exit code as an error
+ message.
- .. c:member:: wchar_t** items
+ The error message remains valid until another ``PyInitConfig``
+ function is called with *config*. The caller doesn't have to free the
+ error message.
- List items.
-PyStatus
---------
+.. c:function:: int PyInitConfig_GetExitCode(PyInitConfig* config, int *exitcode)
-.. c:type:: PyStatus
+ Get the *config* exit code.
- Structure to store an initialization function status: success, error
- or exit.
+ * Set *\*exitcode* and return ``1`` if *config* has an exit code set.
+ * Return ``0`` if *config* has no exit code set.
- For an error, it can store the C function name which created the error.
+ Only the ``Py_InitializeFromInitConfig()`` function can set an exit
+ code if the ``parse_argv`` option is non-zero.
- Structure fields:
+ An exit code can be set when parsing the command line failed (exit
+ code ``2``) or when a command line option asks to display the command
+ line help (exit code ``0``).
- .. c:member:: int exitcode
- Exit code. Argument passed to ``exit()``.
+Get Options
+-----------
- .. c:member:: const char *err_msg
+The configuration option *name* parameter must be a non-NULL
+null-terminated UTF-8 encoded string.
- Error message.
+.. c:function:: int PyInitConfig_HasOption(PyInitConfig *config, const char *name)
- .. c:member:: const char *func
+ Test if the configuration has an option called *name*.
- Name of the function which created an error, can be ``NULL``.
+ Return ``1`` if the option exists, or return ``0`` otherwise.
- .. c:namespace:: NULL
- Functions to create a status:
+.. c:function:: int PyInitConfig_GetInt(PyInitConfig *config, const char *name, int64_t *value)
- .. c:function:: PyStatus PyStatus_Ok(void)
+ Get an integer configuration option.
- Success.
+ * Set *\*value*, and return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
- .. c:function:: PyStatus PyStatus_Error(const char *err_msg)
- Initialization error with a message.
+.. c:function:: int PyInitConfig_GetStr(PyInitConfig *config, const char *name, char **value)
- *err_msg* must not be ``NULL``.
+ Get a string configuration option as a null-terminated UTF-8
+ encoded string.
- .. c:function:: PyStatus PyStatus_NoMemory(void)
+ * Set *\*value*, and return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
- Memory allocation failure (out of memory).
+ *\*value* can be set to ``NULL`` if the option is an optional string and the
+ option is unset.
- .. c:function:: PyStatus PyStatus_Exit(int exitcode)
+ On success, the string must be released with ``free(value)`` if it's not
+ ``NULL``.
- Exit Python with the specified exit code.
- Functions to handle a status:
+.. c:function:: int PyInitConfig_GetStrList(PyInitConfig *config, const char *name, size_t *length, char ***items)
- .. c:function:: int PyStatus_Exception(PyStatus status)
+ Get a string list configuration option as an array of
+ null-terminated UTF-8 encoded strings.
- Is the status an error or an exit? If true, the exception must be
- handled; by calling :c:func:`Py_ExitStatusException` for example.
+ * Set *\*length* and *\*value*, and return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
- .. c:function:: int PyStatus_IsError(PyStatus status)
+ On success, the string list must be released with
+ ``PyInitConfig_FreeStrList(length, items)``.
- Is the result an error?
- .. c:function:: int PyStatus_IsExit(PyStatus status)
+.. c:function:: void PyInitConfig_FreeStrList(size_t length, char **items)
- Is the result an exit?
+ Free memory of a string list created by
+ ``PyInitConfig_GetStrList()``.
- .. c:function:: void Py_ExitStatusException(PyStatus status)
- Call ``exit(exitcode)`` if *status* is an exit. Print the error
- message and exit with a non-zero exit code if *status* is an error. Must
- only be called if ``PyStatus_Exception(status)`` is non-zero.
+Set Options
+-----------
-.. note::
- Internally, Python uses macros which set ``PyStatus.func``,
- whereas functions to create a status set ``func`` to ``NULL``.
+The configuration option *name* parameter must be a non-NULL null-terminated
+UTF-8 encoded string.
-Example::
+Some configuration options have side effects on other options. This logic is
+only implemented when ``Py_InitializeFromInitConfig()`` is called, not by the
+"Set" functions below. For example, setting ``dev_mode`` to ``1`` does not set
+``faulthandler`` to ``1``.
- PyStatus alloc(void **ptr, size_t size)
- {
- *ptr = PyMem_RawMalloc(size);
- if (*ptr == NULL) {
- return PyStatus_NoMemory();
- }
- return PyStatus_Ok();
- }
+.. c:function:: int PyInitConfig_SetInt(PyInitConfig *config, const char *name, int64_t value)
- int main(int argc, char **argv)
- {
- void *ptr;
- PyStatus status = alloc(&ptr, 16);
- if (PyStatus_Exception(status)) {
- Py_ExitStatusException(status);
- }
- PyMem_Free(ptr);
- return 0;
- }
+ Set an integer configuration option.
+ * Return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
-PyPreConfig
------------
-.. c:type:: PyPreConfig
+.. c:function:: int PyInitConfig_SetStr(PyInitConfig *config, const char *name, const char *value)
- Structure used to preinitialize Python.
+ Set a string configuration option from a null-terminated UTF-8
+ encoded string. The string is copied.
- .. c:namespace:: NULL
+ * Return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
- Function to initialize a preconfiguration:
- .. c:function:: void PyPreConfig_InitPythonConfig(PyPreConfig *preconfig)
+.. c:function:: int PyInitConfig_SetStrList(PyInitConfig *config, const char *name, size_t length, char * const *items)
- Initialize the preconfiguration with :ref:`Python Configuration
- <init-python-config>`.
+ Set a string list configuration option from an array of
+ null-terminated UTF-8 encoded strings. The string list is copied.
- .. c:function:: void PyPreConfig_InitIsolatedConfig(PyPreConfig *preconfig)
+ * Return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
- Initialize the preconfiguration with :ref:`Isolated Configuration
- <init-isolated-conf>`.
- .. c:namespace:: PyPreConfig
+Module
+------
- Structure fields:
+.. c:function:: int PyInitConfig_AddModule(PyInitConfig *config, const char *name, PyObject* (*initfunc)(void))
- .. c:member:: int allocator
-
- Name of the Python memory allocators:
+ Add a built-in extension module to the table of built-in modules.
- * ``PYMEM_ALLOCATOR_NOT_SET`` (``0``): don't change memory allocators
- (use defaults).
- * ``PYMEM_ALLOCATOR_DEFAULT`` (``1``): :ref:`default memory allocators
- <default-memory-allocators>`.
- * ``PYMEM_ALLOCATOR_DEBUG`` (``2``): :ref:`default memory allocators
- <default-memory-allocators>` with :ref:`debug hooks
- <pymem-debug-hooks>`.
- * ``PYMEM_ALLOCATOR_MALLOC`` (``3``): use ``malloc()`` of the C library.
- * ``PYMEM_ALLOCATOR_MALLOC_DEBUG`` (``4``): force usage of
- ``malloc()`` with :ref:`debug hooks <pymem-debug-hooks>`.
- * ``PYMEM_ALLOCATOR_PYMALLOC`` (``5``): :ref:`Python pymalloc memory
- allocator <pymalloc>`.
- * ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` (``6``): :ref:`Python pymalloc
- memory allocator <pymalloc>` with :ref:`debug hooks
- <pymem-debug-hooks>`.
- * ``PYMEM_ALLOCATOR_MIMALLOC`` (``6``): use ``mimalloc``, a fast
- malloc replacement.
- * ``PYMEM_ALLOCATOR_MIMALLOC_DEBUG`` (``7``): use ``mimalloc``, a fast
- malloc replacement with :ref:`debug hooks <pymem-debug-hooks>`.
+ The new module can be imported by the name *name*, and uses the function
+ *initfunc* as the initialization function called on the first attempted
+ import.
+ * Return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
- ``PYMEM_ALLOCATOR_PYMALLOC`` and ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` are
- not supported if Python is :option:`configured using --without-pymalloc
- <--without-pymalloc>`.
+ If Python is initialized multiple times, ``PyInitConfig_AddModule()`` must
+ be called at each Python initialization.
- ``PYMEM_ALLOCATOR_MIMALLOC`` and ``PYMEM_ALLOCATOR_MIMALLOC_DEBUG`` are
- not supported if Python is :option:`configured using --without-mimalloc
- <--without-mimalloc>` or if the underlying atomic support isn't
- available.
+ Similar to the :c:func:`PyImport_AppendInittab` function.
- See :ref:`Memory Management <memory>`.
- Default: ``PYMEM_ALLOCATOR_NOT_SET``.
+Initialize Python
+-----------------
- .. c:member:: int configure_locale
+.. c:function:: int Py_InitializeFromInitConfig(PyInitConfig *config)
- Set the LC_CTYPE locale to the user preferred locale.
+ Initialize Python from the initialization configuration.
- If equals to ``0``, set :c:member:`~PyPreConfig.coerce_c_locale` and
- :c:member:`~PyPreConfig.coerce_c_locale_warn` members to ``0``.
+ * Return ``0`` on success.
+ * Set an error in *config* and return ``-1`` on error.
+ * Set an exit code in *config* and return ``-1`` if Python wants to
+ exit.
- See the :term:`locale encoding`.
+ See ``PyInitConfig_GetExitcode()`` for the exit code case.
- Default: ``1`` in Python config, ``0`` in isolated config.
- .. c:member:: int coerce_c_locale
+Runtime Python configuration API
+================================
- If equals to ``2``, coerce the C locale.
+At runtime, it's possible to get and set configuration options using
+:c:func:`PyConfig_Get` and :c:func:`PyConfig_Set` functions.
- If equals to ``1``, read the LC_CTYPE locale to decide if it should be
- coerced.
+The configuration option *name* parameter must be a non-NULL null-terminated
+UTF-8 encoded string.
- See the :term:`locale encoding`.
+Some options are read from the :mod:`sys` attributes. For example, the option
+``"argv"`` is read from :data:`sys.argv`.
- Default: ``-1`` in Python config, ``0`` in isolated config.
- .. c:member:: int coerce_c_locale_warn
+.. c:function:: PyObject* PyConfig_Get(const char *name)
- If non-zero, emit a warning if the C locale is coerced.
+ Get the current runtime value of a configuration option as a Python object.
- Default: ``-1`` in Python config, ``0`` in isolated config.
+ * Return a new reference on success.
+ * Set an exception and return ``NULL`` on error.
- .. c:member:: int dev_mode
+ The object type depends on the configuration option. It can be:
- :ref:`Python Development Mode <devmode>`: see
- :c:member:`PyConfig.dev_mode`.
+ * ``bool``
+ * ``int``
+ * ``str``
+ * ``list[str]``
+ * ``dict[str, str]``
- Default: ``-1`` in Python mode, ``0`` in isolated mode.
+ The caller must hold the GIL. The function cannot be called before
+ Python initialization nor after Python finalization.
- .. c:member:: int isolated
+ .. versionadded:: 3.14
- Isolated mode: see :c:member:`PyConfig.isolated`.
- Default: ``0`` in Python mode, ``1`` in isolated mode.
+.. c:function:: int PyConfig_GetInt(const char *name, int *value)
- .. c:member:: int legacy_windows_fs_encoding
+ Similar to :c:func:`PyConfig_Get`, but get the value as a C int.
- If non-zero:
+ * Return ``0`` on success.
+ * Set an exception and return ``-1`` on error.
- * Set :c:member:`PyPreConfig.utf8_mode` to ``0``,
- * Set :c:member:`PyConfig.filesystem_encoding` to ``"mbcs"``,
- * Set :c:member:`PyConfig.filesystem_errors` to ``"replace"``.
+ .. versionadded:: 3.14
- Initialized from the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment
- variable value.
- Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
- Windows specific code.
+.. c:function:: PyObject* PyConfig_Names(void)
- Default: ``0``.
+ Get all configuration option names as a ``frozenset``.
- .. c:member:: int parse_argv
+ * Return a new reference on success.
+ * Set an exception and return ``NULL`` on error.
- If non-zero, :c:func:`Py_PreInitializeFromArgs` and
- :c:func:`Py_PreInitializeFromBytesArgs` parse their ``argv`` argument the
- same way the regular Python parses command line arguments: see
- :ref:`Command Line Arguments <using-on-cmdline>`.
+ The caller must hold the GIL. The function cannot be called before
+ Python initialization nor after Python finalization.
- Default: ``1`` in Python config, ``0`` in isolated config.
+ .. versionadded:: 3.14
- .. c:member:: int use_environment
- Use :ref:`environment variables <using-on-envvars>`? See
- :c:member:`PyConfig.use_environment`.
+.. c:function:: int PyConfig_Set(const char *name, PyObject *value)
- Default: ``1`` in Python config and ``0`` in isolated config.
+ Set the current runtime value of a configuration option.
- .. c:member:: int utf8_mode
+ * Raise a :exc:`ValueError` if there is no option *name*.
+ * Raise a :exc:`ValueError` if *value* is an invalid value.
+ * Raise a :exc:`ValueError` if the option is read-only (cannot be set).
+ * Raise a :exc:`TypeError` if *value* has not the proper type.
- If non-zero, enable the :ref:`Python UTF-8 Mode <utf8-mode>`.
+ The caller must hold the GIL. The function cannot be called before
+ Python initialization nor after Python finalization.
- Set to ``0`` or ``1`` by the :option:`-X utf8 <-X>` command line option
- and the :envvar:`PYTHONUTF8` environment variable.
+ .. versionadded:: 3.14
- Also set to ``1`` if the ``LC_CTYPE`` locale is ``C`` or ``POSIX``.
- Default: ``-1`` in Python config and ``0`` in isolated config.
+.. _pyconfig_api:
+PyConfig C API
+==============
-.. _c-preinit:
+.. versionadded:: 3.8
-Preinitialize Python with PyPreConfig
--------------------------------------
+Python can be initialized with :c:func:`Py_InitializeFromConfig` and the
+:c:type:`PyConfig` structure. It can be preinitialized with
+:c:func:`Py_PreInitialize` and the :c:type:`PyPreConfig` structure.
-The preinitialization of Python:
+There are two kinds of configuration:
-* Set the Python memory allocators (:c:member:`PyPreConfig.allocator`)
-* Configure the LC_CTYPE locale (:term:`locale encoding`)
-* Set the :ref:`Python UTF-8 Mode <utf8-mode>`
- (:c:member:`PyPreConfig.utf8_mode`)
+* The :ref:`Python Configuration <init-python-config>` can be used to build a
+ customized Python which behaves as the regular Python. For example,
+ environment variables and command line arguments are used to configure
+ Python.
-The current preconfiguration (``PyPreConfig`` type) is stored in
-``_PyRuntime.preconfig``.
+* The :ref:`Isolated Configuration <init-isolated-conf>` can be used to embed
+ Python into an application. It isolates Python from the system. For example,
+ environment variables are ignored, the LC_CTYPE locale is left unchanged and
+ no signal handler is registered.
-Functions to preinitialize Python:
+The :c:func:`Py_RunMain` function can be used to write a customized Python
+program.
-.. c:function:: PyStatus Py_PreInitialize(const PyPreConfig *preconfig)
+See also :ref:`Initialization, Finalization, and Threads <initialization>`.
- Preinitialize Python from *preconfig* preconfiguration.
+.. seealso::
+ :pep:`587` "Python Initialization Configuration".
- *preconfig* must not be ``NULL``.
-.. c:function:: PyStatus Py_PreInitializeFromBytesArgs(const PyPreConfig *preconfig, int argc, char * const *argv)
+Example
+-------
- Preinitialize Python from *preconfig* preconfiguration.
+Example of customized Python always running in isolated mode::
- Parse *argv* command line arguments (bytes strings) if
- :c:member:`~PyPreConfig.parse_argv` of *preconfig* is non-zero.
+ int main(int argc, char **argv)
+ {
+ PyStatus status;
- *preconfig* must not be ``NULL``.
+ PyConfig config;
+ PyConfig_InitPythonConfig(&config);
+ config.isolated = 1;
-.. c:function:: PyStatus Py_PreInitializeFromArgs(const PyPreConfig *preconfig, int argc, wchar_t * const * argv)
+ /* Decode command line arguments.
+ Implicitly preinitialize Python (in isolated mode). */
+ status = PyConfig_SetBytesArgv(&config, argc, argv);
+ if (PyStatus_Exception(status)) {
+ goto exception;
+ }
- Preinitialize Python from *preconfig* preconfiguration.
+ status = Py_InitializeFromConfig(&config);
+ if (PyStatus_Exception(status)) {
+ goto exception;
+ }
+ PyConfig_Clear(&config);
- Parse *argv* command line arguments (wide strings) if
- :c:member:`~PyPreConfig.parse_argv` of *preconfig* is non-zero.
+ return Py_RunMain();
- *preconfig* must not be ``NULL``.
+ exception:
+ PyConfig_Clear(&config);
+ if (PyStatus_IsExit(status)) {
+ return status.exitcode;
+ }
+ /* Display the error message and exit the process with
+ non-zero exit code */
+ Py_ExitStatusException(status);
+ }
-The caller is responsible to handle exceptions (error or exit) using
-:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`.
-For :ref:`Python Configuration <init-python-config>`
-(:c:func:`PyPreConfig_InitPythonConfig`), if Python is initialized with
-command line arguments, the command line arguments must also be passed to
-preinitialize Python, since they have an effect on the pre-configuration
-like encodings. For example, the :option:`-X utf8 <-X>` command line option
-enables the :ref:`Python UTF-8 Mode <utf8-mode>`.
+PyWideStringList
+----------------
-``PyMem_SetAllocator()`` can be called after :c:func:`Py_PreInitialize` and
-before :c:func:`Py_InitializeFromConfig` to install a custom memory allocator.
-It can be called before :c:func:`Py_PreInitialize` if
-:c:member:`PyPreConfig.allocator` is set to ``PYMEM_ALLOCATOR_NOT_SET``.
+.. c:type:: PyWideStringList
-Python memory allocation functions like :c:func:`PyMem_RawMalloc` must not be
-used before the Python preinitialization, whereas calling directly ``malloc()``
-and ``free()`` is always safe. :c:func:`Py_DecodeLocale` must not be called
-before the Python preinitialization.
+ List of ``wchar_t*`` strings.
-Example using the preinitialization to enable
-the :ref:`Python UTF-8 Mode <utf8-mode>`::
+ If *length* is non-zero, *items* must be non-``NULL`` and all strings must be
+ non-``NULL``.
- PyStatus status;
- PyPreConfig preconfig;
- PyPreConfig_InitPythonConfig(&preconfig);
+ .. c:namespace:: NULL
- preconfig.utf8_mode = 1;
+ Methods:
- status = Py_PreInitialize(&preconfig);
- if (PyStatus_Exception(status)) {
- Py_ExitStatusException(status);
- }
+ .. c:function:: PyStatus PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
- /* at this point, Python speaks UTF-8 */
+ Append *item* to *list*.
- Py_Initialize();
- /* ... use Python API here ... */
- Py_Finalize();
+ Python must be preinitialized to call this function.
+ .. c:function:: PyStatus PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item)
-PyConfig
---------
+ Insert *item* into *list* at *index*.
-.. c:type:: PyConfig
+ If *index* is greater than or equal to *list* length, append *item* to
+ *list*.
- Structure containing most parameters to configure Python.
+ *index* must be greater than or equal to ``0``.
- When done, the :c:func:`PyConfig_Clear` function must be used to release the
- configuration memory.
+ Python must be preinitialized to call this function.
- .. c:namespace:: NULL
+ .. c:namespace:: PyWideStringList
- Structure methods:
+ Structure fields:
- .. c:function:: void PyConfig_InitPythonConfig(PyConfig *config)
+ .. c:member:: Py_ssize_t length
- Initialize configuration with the :ref:`Python Configuration
- <init-python-config>`.
+ List length.
- .. c:function:: void PyConfig_InitIsolatedConfig(PyConfig *config)
+ .. c:member:: wchar_t** items
- Initialize configuration with the :ref:`Isolated Configuration
- <init-isolated-conf>`.
+ List items.
- .. c:function:: PyStatus PyConfig_SetString(PyConfig *config, wchar_t * const *config_str, const wchar_t *str)
+PyStatus
+--------
- Copy the wide character string *str* into ``*config_str``.
+.. c:type:: PyStatus
- :ref:`Preinitialize Python <c-preinit>` if needed.
+ Structure to store an initialization function status: success, error
+ or exit.
- .. c:function:: PyStatus PyConfig_SetBytesString(PyConfig *config, wchar_t * const *config_str, const char *str)
+ For an error, it can store the C function name which created the error.
- Decode *str* using :c:func:`Py_DecodeLocale` and set the result into
- ``*config_str``.
+ Structure fields:
- :ref:`Preinitialize Python <c-preinit>` if needed.
+ .. c:member:: int exitcode
- .. c:function:: PyStatus PyConfig_SetArgv(PyConfig *config, int argc, wchar_t * const *argv)
+ Exit code. Argument passed to ``exit()``.
- Set command line arguments (:c:member:`~PyConfig.argv` member of
- *config*) from the *argv* list of wide character strings.
+ .. c:member:: const char *err_msg
- :ref:`Preinitialize Python <c-preinit>` if needed.
+ Error message.
- .. c:function:: PyStatus PyConfig_SetBytesArgv(PyConfig *config, int argc, char * const *argv)
+ .. c:member:: const char *func
- Set command line arguments (:c:member:`~PyConfig.argv` member of
- *config*) from the *argv* list of bytes strings. Decode bytes using
- :c:func:`Py_DecodeLocale`.
+ Name of the function which created an error, can be ``NULL``.
- :ref:`Preinitialize Python <c-preinit>` if needed.
+ .. c:namespace:: NULL
- .. c:function:: PyStatus PyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list, Py_ssize_t length, wchar_t **items)
+ Functions to create a status:
- Set the list of wide strings *list* to *length* and *items*.
+ .. c:function:: PyStatus PyStatus_Ok(void)
- :ref:`Preinitialize Python <c-preinit>` if needed.
+ Success.
- .. c:function:: PyStatus PyConfig_Read(PyConfig *config)
+ .. c:function:: PyStatus PyStatus_Error(const char *err_msg)
- Read all Python configuration.
+ Initialization error with a message.
- Fields which are already initialized are left unchanged.
+ *err_msg* must not be ``NULL``.
- Fields for :ref:`path configuration <init-path-config>` are no longer
- calculated or modified when calling this function, as of Python 3.11.
+ .. c:function:: PyStatus PyStatus_NoMemory(void)
- The :c:func:`PyConfig_Read` function only parses
- :c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv`
- is set to ``2`` after arguments are parsed. Since Python arguments are
- stripped from :c:member:`PyConfig.argv`, parsing arguments twice would
- parse the application options as Python options.
+ Memory allocation failure (out of memory).
- :ref:`Preinitialize Python <c-preinit>` if needed.
+ .. c:function:: PyStatus PyStatus_Exit(int exitcode)
- .. versionchanged:: 3.10
- The :c:member:`PyConfig.argv` arguments are now only parsed once,
- :c:member:`PyConfig.parse_argv` is set to ``2`` after arguments are
- parsed, and arguments are only parsed if
- :c:member:`PyConfig.parse_argv` equals ``1``.
+ Exit Python with the specified exit code.
- .. versionchanged:: 3.11
- :c:func:`PyConfig_Read` no longer calculates all paths, and so fields
- listed under :ref:`Python Path Configuration <init-path-config>` may
- no longer be updated until :c:func:`Py_InitializeFromConfig` is
- called.
+ Functions to handle a status:
- .. c:function:: void PyConfig_Clear(PyConfig *config)
+ .. c:function:: int PyStatus_Exception(PyStatus status)
- Release configuration memory.
+ Is the status an error or an exit? If true, the exception must be
+ handled; by calling :c:func:`Py_ExitStatusException` for example.
- Most ``PyConfig`` methods :ref:`preinitialize Python <c-preinit>` if needed.
- In that case, the Python preinitialization configuration
- (:c:type:`PyPreConfig`) in based on the :c:type:`PyConfig`. If configuration
- fields which are in common with :c:type:`PyPreConfig` are tuned, they must
- be set before calling a :c:type:`PyConfig` method:
+ .. c:function:: int PyStatus_IsError(PyStatus status)
- * :c:member:`PyConfig.dev_mode`
- * :c:member:`PyConfig.isolated`
- * :c:member:`PyConfig.parse_argv`
- * :c:member:`PyConfig.use_environment`
+ Is the result an error?
- Moreover, if :c:func:`PyConfig_SetArgv` or :c:func:`PyConfig_SetBytesArgv`
- is used, this method must be called before other methods, since the
- preinitialization configuration depends on command line arguments (if
- :c:member:`~PyConfig.parse_argv` is non-zero).
+ .. c:function:: int PyStatus_IsExit(PyStatus status)
- The caller of these methods is responsible to handle exceptions (error or
- exit) using ``PyStatus_Exception()`` and ``Py_ExitStatusException()``.
+ Is the result an exit?
- .. c:namespace:: PyConfig
+ .. c:function:: void Py_ExitStatusException(PyStatus status)
- Structure fields:
+ Call ``exit(exitcode)`` if *status* is an exit. Print the error
+ message and exit with a non-zero exit code if *status* is an error. Must
+ only be called if ``PyStatus_Exception(status)`` is non-zero.
- .. c:member:: PyWideStringList argv
+.. note::
+ Internally, Python uses macros which set ``PyStatus.func``,
+ whereas functions to create a status set ``func`` to ``NULL``.
- .. index::
- single: main()
- single: argv (in module sys)
+Example::
- Set :data:`sys.argv` command line arguments based on
- :c:member:`~PyConfig.argv`. These parameters are similar to those passed
- to the program's :c:func:`main` function with the difference that the
- first entry should refer to the script file to be executed rather than
- the executable hosting the Python interpreter. If there isn't a script
- that will be run, the first entry in :c:member:`~PyConfig.argv` can be an
- empty string.
+ PyStatus alloc(void **ptr, size_t size)
+ {
+ *ptr = PyMem_RawMalloc(size);
+ if (*ptr == NULL) {
+ return PyStatus_NoMemory();
+ }
+ return PyStatus_Ok();
+ }
- Set :c:member:`~PyConfig.parse_argv` to ``1`` to parse
- :c:member:`~PyConfig.argv` the same way the regular Python parses Python
- command line arguments and then to strip Python arguments from
- :c:member:`~PyConfig.argv`.
+ int main(int argc, char **argv)
+ {
+ void *ptr;
+ PyStatus status = alloc(&ptr, 16);
+ if (PyStatus_Exception(status)) {
+ Py_ExitStatusException(status);
+ }
+ PyMem_Free(ptr);
+ return 0;
+ }
- If :c:member:`~PyConfig.argv` is empty, an empty string is added to
- ensure that :data:`sys.argv` always exists and is never empty.
- Default: ``NULL``.
+PyPreConfig
+-----------
- See also the :c:member:`~PyConfig.orig_argv` member.
+.. c:type:: PyPreConfig
- .. c:member:: int safe_path
+ Structure used to preinitialize Python.
- If equals to zero, ``Py_RunMain()`` prepends a potentially unsafe path to
- :data:`sys.path` at startup:
+ .. c:namespace:: NULL
- * If :c:member:`argv[0] <PyConfig.argv>` is equal to ``L"-m"``
- (``python -m module``), prepend the current working directory.
- * If running a script (``python script.py``), prepend the script's
- directory. If it's a symbolic link, resolve symbolic links.
- * Otherwise (``python -c code`` and ``python``), prepend an empty string,
- which means the current working directory.
+ Function to initialize a preconfiguration:
- Set to ``1`` by the :option:`-P` command line option and the
- :envvar:`PYTHONSAFEPATH` environment variable.
+ .. c:function:: void PyPreConfig_InitPythonConfig(PyPreConfig *preconfig)
- Default: ``0`` in Python config, ``1`` in isolated config.
+ Initialize the preconfiguration with :ref:`Python Configuration
+ <init-python-config>`.
- .. versionadded:: 3.11
+ .. c:function:: void PyPreConfig_InitIsolatedConfig(PyPreConfig *preconfig)
- .. c:member:: wchar_t* base_exec_prefix
+ Initialize the preconfiguration with :ref:`Isolated Configuration
+ <init-isolated-conf>`.
- :data:`sys.base_exec_prefix`.
+ .. c:namespace:: PyPreConfig
- Default: ``NULL``.
+ Structure fields:
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+ .. c:member:: int allocator
- See also :c:member:`PyConfig.exec_prefix`.
+ Name of the Python memory allocators:
- .. c:member:: wchar_t* base_executable
+ * ``PYMEM_ALLOCATOR_NOT_SET`` (``0``): don't change memory allocators
+ (use defaults).
+ * ``PYMEM_ALLOCATOR_DEFAULT`` (``1``): :ref:`default memory allocators
+ <default-memory-allocators>`.
+ * ``PYMEM_ALLOCATOR_DEBUG`` (``2``): :ref:`default memory allocators
+ <default-memory-allocators>` with :ref:`debug hooks
+ <pymem-debug-hooks>`.
+ * ``PYMEM_ALLOCATOR_MALLOC`` (``3``): use ``malloc()`` of the C library.
+ * ``PYMEM_ALLOCATOR_MALLOC_DEBUG`` (``4``): force usage of
+ ``malloc()`` with :ref:`debug hooks <pymem-debug-hooks>`.
+ * ``PYMEM_ALLOCATOR_PYMALLOC`` (``5``): :ref:`Python pymalloc memory
+ allocator <pymalloc>`.
+ * ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` (``6``): :ref:`Python pymalloc
+ memory allocator <pymalloc>` with :ref:`debug hooks
+ <pymem-debug-hooks>`.
+ * ``PYMEM_ALLOCATOR_MIMALLOC`` (``6``): use ``mimalloc``, a fast
+ malloc replacement.
+ * ``PYMEM_ALLOCATOR_MIMALLOC_DEBUG`` (``7``): use ``mimalloc``, a fast
+ malloc replacement with :ref:`debug hooks <pymem-debug-hooks>`.
- Python base executable: :data:`sys._base_executable`.
- Set by the :envvar:`__PYVENV_LAUNCHER__` environment variable.
+ ``PYMEM_ALLOCATOR_PYMALLOC`` and ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` are
+ not supported if Python is :option:`configured using --without-pymalloc
+ <--without-pymalloc>`.
- Set from :c:member:`PyConfig.executable` if ``NULL``.
+ ``PYMEM_ALLOCATOR_MIMALLOC`` and ``PYMEM_ALLOCATOR_MIMALLOC_DEBUG`` are
+ not supported if Python is :option:`configured using --without-mimalloc
+ <--without-mimalloc>` or if the underlying atomic support isn't
+ available.
- Default: ``NULL``.
+ See :ref:`Memory Management <memory>`.
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+ Default: ``PYMEM_ALLOCATOR_NOT_SET``.
- See also :c:member:`PyConfig.executable`.
+ .. c:member:: int configure_locale
- .. c:member:: wchar_t* base_prefix
+ Set the LC_CTYPE locale to the user preferred locale.
- :data:`sys.base_prefix`.
+ If equals to ``0``, set :c:member:`~PyPreConfig.coerce_c_locale` and
+ :c:member:`~PyPreConfig.coerce_c_locale_warn` members to ``0``.
- Default: ``NULL``.
+ See the :term:`locale encoding`.
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+ Default: ``1`` in Python config, ``0`` in isolated config.
- See also :c:member:`PyConfig.prefix`.
+ .. c:member:: int coerce_c_locale
- .. c:member:: int buffered_stdio
+ If equals to ``2``, coerce the C locale.
- If equals to ``0`` and :c:member:`~PyConfig.configure_c_stdio` is non-zero,
- disable buffering on the C streams stdout and stderr.
+ If equals to ``1``, read the LC_CTYPE locale to decide if it should be
+ coerced.
- Set to ``0`` by the :option:`-u` command line option and the
- :envvar:`PYTHONUNBUFFERED` environment variable.
+ See the :term:`locale encoding`.
- stdin is always opened in buffered mode.
+ Default: ``-1`` in Python config, ``0`` in isolated config.
- Default: ``1``.
+ .. c:member:: int coerce_c_locale_warn
- .. c:member:: int bytes_warning
+ If non-zero, emit a warning if the C locale is coerced.
- If equals to ``1``, issue a warning when comparing :class:`bytes` or
- :class:`bytearray` with :class:`str`, or comparing :class:`bytes` with
- :class:`int`.
-
- If equal or greater to ``2``, raise a :exc:`BytesWarning` exception in these
- cases.
-
- Incremented by the :option:`-b` command line option.
+ Default: ``-1`` in Python config, ``0`` in isolated config.
- Default: ``0``.
+ .. c:member:: int dev_mode
- .. c:member:: int warn_default_encoding
+ :ref:`Python Development Mode <devmode>`: see
+ :c:member:`PyConfig.dev_mode`.
- If non-zero, emit a :exc:`EncodingWarning` warning when :class:`io.TextIOWrapper`
- uses its default encoding. See :ref:`io-encoding-warning` for details.
+ Default: ``-1`` in Python mode, ``0`` in isolated mode.
- Default: ``0``.
+ .. c:member:: int isolated
- .. versionadded:: 3.10
+ Isolated mode: see :c:member:`PyConfig.isolated`.
- .. c:member:: int code_debug_ranges
+ Default: ``0`` in Python mode, ``1`` in isolated mode.
- If equals to ``0``, disables the inclusion of the end line and column
- mappings in code objects. Also disables traceback printing carets to
- specific error locations.
+ .. c:member:: int legacy_windows_fs_encoding
- Set to ``0`` by the :envvar:`PYTHONNODEBUGRANGES` environment variable
- and by the :option:`-X no_debug_ranges <-X>` command line option.
+ If non-zero:
- Default: ``1``.
+ * Set :c:member:`PyPreConfig.utf8_mode` to ``0``,
+ * Set :c:member:`PyConfig.filesystem_encoding` to ``"mbcs"``,
+ * Set :c:member:`PyConfig.filesystem_errors` to ``"replace"``.
- .. versionadded:: 3.11
+ Initialized from the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment
+ variable value.
- .. c:member:: wchar_t* check_hash_pycs_mode
+ Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
+ Windows specific code.
- Control the validation behavior of hash-based ``.pyc`` files:
- value of the :option:`--check-hash-based-pycs` command line option.
+ Default: ``0``.
- Valid values:
+ .. c:member:: int parse_argv
- - ``L"always"``: Hash the source file for invalidation regardless of
- value of the 'check_source' flag.
- - ``L"never"``: Assume that hash-based pycs always are valid.
- - ``L"default"``: The 'check_source' flag in hash-based pycs
- determines invalidation.
+ If non-zero, :c:func:`Py_PreInitializeFromArgs` and
+ :c:func:`Py_PreInitializeFromBytesArgs` parse their ``argv`` argument the
+ same way the regular Python parses command line arguments: see
+ :ref:`Command Line Arguments <using-on-cmdline>`.
- Default: ``L"default"``.
+ Default: ``1`` in Python config, ``0`` in isolated config.
- See also :pep:`552` "Deterministic pycs".
+ .. c:member:: int use_environment
- .. c:member:: int configure_c_stdio
+ Use :ref:`environment variables <using-on-envvars>`? See
+ :c:member:`PyConfig.use_environment`.
- If non-zero, configure C standard streams:
+ Default: ``1`` in Python config and ``0`` in isolated config.
- * On Windows, set the binary mode (``O_BINARY``) on stdin, stdout and
- stderr.
- * If :c:member:`~PyConfig.buffered_stdio` equals zero, disable buffering
- of stdin, stdout and stderr streams.
- * If :c:member:`~PyConfig.interactive` is non-zero, enable stream
- buffering on stdin and stdout (only stdout on Windows).
+ .. c:member:: int utf8_mode
- Default: ``1`` in Python config, ``0`` in isolated config.
+ If non-zero, enable the :ref:`Python UTF-8 Mode <utf8-mode>`.
- .. c:member:: int dev_mode
+ Set to ``0`` or ``1`` by the :option:`-X utf8 <-X>` command line option
+ and the :envvar:`PYTHONUTF8` environment variable.
- If non-zero, enable the :ref:`Python Development Mode <devmode>`.
+ Also set to ``1`` if the ``LC_CTYPE`` locale is ``C`` or ``POSIX``.
- Set to ``1`` by the :option:`-X dev <-X>` option and the
- :envvar:`PYTHONDEVMODE` environment variable.
+ Default: ``-1`` in Python config and ``0`` in isolated config.
- Default: ``-1`` in Python mode, ``0`` in isolated mode.
- .. c:member:: int dump_refs
+.. _c-preinit:
- Dump Python references?
+Preinitialize Python with PyPreConfig
+-------------------------------------
- If non-zero, dump all objects which are still alive at exit.
+The preinitialization of Python:
- Set to ``1`` by the :envvar:`PYTHONDUMPREFS` environment variable.
+* Set the Python memory allocators (:c:member:`PyPreConfig.allocator`)
+* Configure the LC_CTYPE locale (:term:`locale encoding`)
+* Set the :ref:`Python UTF-8 Mode <utf8-mode>`
+ (:c:member:`PyPreConfig.utf8_mode`)
- Needs a special build of Python with the ``Py_TRACE_REFS`` macro defined:
- see the :option:`configure --with-trace-refs option <--with-trace-refs>`.
+The current preconfiguration (``PyPreConfig`` type) is stored in
+``_PyRuntime.preconfig``.
- Default: ``0``.
+Functions to preinitialize Python:
- .. c:member:: wchar_t* exec_prefix
+.. c:function:: PyStatus Py_PreInitialize(const PyPreConfig *preconfig)
- The site-specific directory prefix where the platform-dependent Python
- files are installed: :data:`sys.exec_prefix`.
+ Preinitialize Python from *preconfig* preconfiguration.
- Default: ``NULL``.
+ *preconfig* must not be ``NULL``.
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+.. c:function:: PyStatus Py_PreInitializeFromBytesArgs(const PyPreConfig *preconfig, int argc, char * const *argv)
- See also :c:member:`PyConfig.base_exec_prefix`.
+ Preinitialize Python from *preconfig* preconfiguration.
- .. c:member:: wchar_t* executable
+ Parse *argv* command line arguments (bytes strings) if
+ :c:member:`~PyPreConfig.parse_argv` of *preconfig* is non-zero.
- The absolute path of the executable binary for the Python interpreter:
- :data:`sys.executable`.
+ *preconfig* must not be ``NULL``.
- Default: ``NULL``.
+.. c:function:: PyStatus Py_PreInitializeFromArgs(const PyPreConfig *preconfig, int argc, wchar_t * const * argv)
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+ Preinitialize Python from *preconfig* preconfiguration.
- See also :c:member:`PyConfig.base_executable`.
+ Parse *argv* command line arguments (wide strings) if
+ :c:member:`~PyPreConfig.parse_argv` of *preconfig* is non-zero.
- .. c:member:: int faulthandler
+ *preconfig* must not be ``NULL``.
- Enable faulthandler?
+The caller is responsible to handle exceptions (error or exit) using
+:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`.
- If non-zero, call :func:`faulthandler.enable` at startup.
+For :ref:`Python Configuration <init-python-config>`
+(:c:func:`PyPreConfig_InitPythonConfig`), if Python is initialized with
+command line arguments, the command line arguments must also be passed to
+preinitialize Python, since they have an effect on the pre-configuration
+like encodings. For example, the :option:`-X utf8 <-X>` command line option
+enables the :ref:`Python UTF-8 Mode <utf8-mode>`.
- Set to ``1`` by :option:`-X faulthandler <-X>` and the
- :envvar:`PYTHONFAULTHANDLER` environment variable.
+``PyMem_SetAllocator()`` can be called after :c:func:`Py_PreInitialize` and
+before :c:func:`Py_InitializeFromConfig` to install a custom memory allocator.
+It can be called before :c:func:`Py_PreInitialize` if
+:c:member:`PyPreConfig.allocator` is set to ``PYMEM_ALLOCATOR_NOT_SET``.
- Default: ``-1`` in Python mode, ``0`` in isolated mode.
+Python memory allocation functions like :c:func:`PyMem_RawMalloc` must not be
+used before the Python preinitialization, whereas calling directly ``malloc()``
+and ``free()`` is always safe. :c:func:`Py_DecodeLocale` must not be called
+before the Python preinitialization.
- .. c:member:: wchar_t* filesystem_encoding
+Example using the preinitialization to enable
+the :ref:`Python UTF-8 Mode <utf8-mode>`::
- :term:`Filesystem encoding <filesystem encoding and error handler>`:
- :func:`sys.getfilesystemencoding`.
+ PyStatus status;
+ PyPreConfig preconfig;
+ PyPreConfig_InitPythonConfig(&preconfig);
- On macOS, Android and VxWorks: use ``"utf-8"`` by default.
+ preconfig.utf8_mode = 1;
- On Windows: use ``"utf-8"`` by default, or ``"mbcs"`` if
- :c:member:`~PyPreConfig.legacy_windows_fs_encoding` of
- :c:type:`PyPreConfig` is non-zero.
+ status = Py_PreInitialize(&preconfig);
+ if (PyStatus_Exception(status)) {
+ Py_ExitStatusException(status);
+ }
- Default encoding on other platforms:
+ /* at this point, Python speaks UTF-8 */
- * ``"utf-8"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero.
- * ``"ascii"`` if Python detects that ``nl_langinfo(CODESET)`` announces
- the ASCII encoding, whereas the ``mbstowcs()`` function
- decodes from a different encoding (usually Latin1).
- * ``"utf-8"`` if ``nl_langinfo(CODESET)`` returns an empty string.
- * Otherwise, use the :term:`locale encoding`:
- ``nl_langinfo(CODESET)`` result.
+ Py_Initialize();
+ /* ... use Python API here ... */
+ Py_Finalize();
- At Python startup, the encoding name is normalized to the Python codec
- name. For example, ``"ANSI_X3.4-1968"`` is replaced with ``"ascii"``.
- See also the :c:member:`~PyConfig.filesystem_errors` member.
+PyConfig
+--------
- .. c:member:: wchar_t* filesystem_errors
+.. c:type:: PyConfig
- :term:`Filesystem error handler <filesystem encoding and error handler>`:
- :func:`sys.getfilesystemencodeerrors`.
+ Structure containing most parameters to configure Python.
- On Windows: use ``"surrogatepass"`` by default, or ``"replace"`` if
- :c:member:`~PyPreConfig.legacy_windows_fs_encoding` of
- :c:type:`PyPreConfig` is non-zero.
+ When done, the :c:func:`PyConfig_Clear` function must be used to release the
+ configuration memory.
- On other platforms: use ``"surrogateescape"`` by default.
+ .. c:namespace:: NULL
- Supported error handlers:
+ Structure methods:
- * ``"strict"``
- * ``"surrogateescape"``
- * ``"surrogatepass"`` (only supported with the UTF-8 encoding)
+ .. c:function:: void PyConfig_InitPythonConfig(PyConfig *config)
- See also the :c:member:`~PyConfig.filesystem_encoding` member.
+ Initialize configuration with the :ref:`Python Configuration
+ <init-python-config>`.
- .. c:member:: unsigned long hash_seed
- .. c:member:: int use_hash_seed
+ .. c:function:: void PyConfig_InitIsolatedConfig(PyConfig *config)
- Randomized hash function seed.
+ Initialize configuration with the :ref:`Isolated Configuration
+ <init-isolated-conf>`.
- If :c:member:`~PyConfig.use_hash_seed` is zero, a seed is chosen randomly
- at Python startup, and :c:member:`~PyConfig.hash_seed` is ignored.
+ .. c:function:: PyStatus PyConfig_SetString(PyConfig *config, wchar_t * const *config_str, const wchar_t *str)
- Set by the :envvar:`PYTHONHASHSEED` environment variable.
+ Copy the wide character string *str* into ``*config_str``.
- Default *use_hash_seed* value: ``-1`` in Python mode, ``0`` in isolated
- mode.
+ :ref:`Preinitialize Python <c-preinit>` if needed.
- .. c:member:: wchar_t* home
+ .. c:function:: PyStatus PyConfig_SetBytesString(PyConfig *config, wchar_t * const *config_str, const char *str)
- Set the default Python "home" directory, that is, the location of the
- standard Python libraries (see :envvar:`PYTHONHOME`).
+ Decode *str* using :c:func:`Py_DecodeLocale` and set the result into
+ ``*config_str``.
- Set by the :envvar:`PYTHONHOME` environment variable.
+ :ref:`Preinitialize Python <c-preinit>` if needed.
- Default: ``NULL``.
+ .. c:function:: PyStatus PyConfig_SetArgv(PyConfig *config, int argc, wchar_t * const *argv)
- Part of the :ref:`Python Path Configuration <init-path-config>` input.
+ Set command line arguments (:c:member:`~PyConfig.argv` member of
+ *config*) from the *argv* list of wide character strings.
- .. c:member:: int import_time
+ :ref:`Preinitialize Python <c-preinit>` if needed.
- If non-zero, profile import time.
+ .. c:function:: PyStatus PyConfig_SetBytesArgv(PyConfig *config, int argc, char * const *argv)
- Set the ``1`` by the :option:`-X importtime <-X>` option and the
- :envvar:`PYTHONPROFILEIMPORTTIME` environment variable.
+ Set command line arguments (:c:member:`~PyConfig.argv` member of
+ *config*) from the *argv* list of bytes strings. Decode bytes using
+ :c:func:`Py_DecodeLocale`.
- Default: ``0``.
+ :ref:`Preinitialize Python <c-preinit>` if needed.
- .. c:member:: int inspect
+ .. c:function:: PyStatus PyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list, Py_ssize_t length, wchar_t **items)
- Enter interactive mode after executing a script or a command.
+ Set the list of wide strings *list* to *length* and *items*.
- If greater than ``0``, enable inspect: when a script is passed as first
- argument or the -c option is used, enter interactive mode after executing
- the script or the command, even when :data:`sys.stdin` does not appear to
- be a terminal.
+ :ref:`Preinitialize Python <c-preinit>` if needed.
- Incremented by the :option:`-i` command line option. Set to ``1`` if the
- :envvar:`PYTHONINSPECT` environment variable is non-empty.
+ .. c:function:: PyStatus PyConfig_Read(PyConfig *config)
- Default: ``0``.
+ Read all Python configuration.
- .. c:member:: int install_signal_handlers
+ Fields which are already initialized are left unchanged.
- Install Python signal handlers?
+ Fields for :ref:`path configuration <init-path-config>` are no longer
+ calculated or modified when calling this function, as of Python 3.11.
- Default: ``1`` in Python mode, ``0`` in isolated mode.
-
- .. c:member:: int interactive
-
- If greater than ``0``, enable the interactive mode (REPL).
-
- Incremented by the :option:`-i` command line option.
+ The :c:func:`PyConfig_Read` function only parses
+ :c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv`
+ is set to ``2`` after arguments are parsed. Since Python arguments are
+ stripped from :c:member:`PyConfig.argv`, parsing arguments twice would
+ parse the application options as Python options.
- Default: ``0``.
+ :ref:`Preinitialize Python <c-preinit>` if needed.
- .. c:member:: int int_max_str_digits
+ .. versionchanged:: 3.10
+ The :c:member:`PyConfig.argv` arguments are now only parsed once,
+ :c:member:`PyConfig.parse_argv` is set to ``2`` after arguments are
+ parsed, and arguments are only parsed if
+ :c:member:`PyConfig.parse_argv` equals ``1``.
- Configures the :ref:`integer string conversion length limitation
- <int_max_str_digits>`. An initial value of ``-1`` means the value will
- be taken from the command line or environment or otherwise default to
- 4300 (:data:`sys.int_info.default_max_str_digits`). A value of ``0``
- disables the limitation. Values greater than zero but less than 640
- (:data:`sys.int_info.str_digits_check_threshold`) are unsupported and
- will produce an error.
+ .. versionchanged:: 3.11
+ :c:func:`PyConfig_Read` no longer calculates all paths, and so fields
+ listed under :ref:`Python Path Configuration <init-path-config>` may
+ no longer be updated until :c:func:`Py_InitializeFromConfig` is
+ called.
- Configured by the :option:`-X int_max_str_digits <-X>` command line
- flag or the :envvar:`PYTHONINTMAXSTRDIGITS` environment variable.
+ .. c:function:: void PyConfig_Clear(PyConfig *config)
- Default: ``-1`` in Python mode. 4300
- (:data:`sys.int_info.default_max_str_digits`) in isolated mode.
+ Release configuration memory.
- .. versionadded:: 3.12
+ Most ``PyConfig`` methods :ref:`preinitialize Python <c-preinit>` if needed.
+ In that case, the Python preinitialization configuration
+ (:c:type:`PyPreConfig`) in based on the :c:type:`PyConfig`. If configuration
+ fields which are in common with :c:type:`PyPreConfig` are tuned, they must
+ be set before calling a :c:type:`PyConfig` method:
- .. c:member:: int cpu_count
+ * :c:member:`PyConfig.dev_mode`
+ * :c:member:`PyConfig.isolated`
+ * :c:member:`PyConfig.parse_argv`
+ * :c:member:`PyConfig.use_environment`
- If the value of :c:member:`~PyConfig.cpu_count` is not ``-1`` then it will
- override the return values of :func:`os.cpu_count`,
- :func:`os.process_cpu_count`, and :func:`multiprocessing.cpu_count`.
+ Moreover, if :c:func:`PyConfig_SetArgv` or :c:func:`PyConfig_SetBytesArgv`
+ is used, this method must be called before other methods, since the
+ preinitialization configuration depends on command line arguments (if
+ :c:member:`~PyConfig.parse_argv` is non-zero).
- Configured by the :samp:`-X cpu_count={n|default}` command line
- flag or the :envvar:`PYTHON_CPU_COUNT` environment variable.
+ The caller of these methods is responsible to handle exceptions (error or
+ exit) using ``PyStatus_Exception()`` and ``Py_ExitStatusException()``.
- Default: ``-1``.
+ .. c:namespace:: PyConfig
- .. versionadded:: 3.13
+ Structure fields:
- .. c:member:: int isolated
+ .. c:member:: PyWideStringList argv
- If greater than ``0``, enable isolated mode:
+ .. index::
+ single: main()
+ single: argv (in module sys)
- * Set :c:member:`~PyConfig.safe_path` to ``1``:
- don't prepend a potentially unsafe path to :data:`sys.path` at Python
- startup, such as the current directory, the script's directory or an
- empty string.
- * Set :c:member:`~PyConfig.use_environment` to ``0``: ignore ``PYTHON``
- environment variables.
- * Set :c:member:`~PyConfig.user_site_directory` to ``0``: don't add the user
- site directory to :data:`sys.path`.
- * Python REPL doesn't import :mod:`readline` nor enable default readline
- configuration on interactive prompts.
+ Set :data:`sys.argv` command line arguments based on
+ :c:member:`~PyConfig.argv`. These parameters are similar to those passed
+ to the program's :c:func:`main` function with the difference that the
+ first entry should refer to the script file to be executed rather than
+ the executable hosting the Python interpreter. If there isn't a script
+ that will be run, the first entry in :c:member:`~PyConfig.argv` can be an
+ empty string.
- Set to ``1`` by the :option:`-I` command line option.
+ Set :c:member:`~PyConfig.parse_argv` to ``1`` to parse
+ :c:member:`~PyConfig.argv` the same way the regular Python parses Python
+ command line arguments and then to strip Python arguments from
+ :c:member:`~PyConfig.argv`.
- Default: ``0`` in Python mode, ``1`` in isolated mode.
+ If :c:member:`~PyConfig.argv` is empty, an empty string is added to
+ ensure that :data:`sys.argv` always exists and is never empty.
- See also the :ref:`Isolated Configuration <init-isolated-conf>` and
- :c:member:`PyPreConfig.isolated`.
+ Default: ``NULL``.
- .. c:member:: int legacy_windows_stdio
+ See also the :c:member:`~PyConfig.orig_argv` member.
- If non-zero, use :class:`io.FileIO` instead of
- :class:`!io._WindowsConsoleIO` for :data:`sys.stdin`, :data:`sys.stdout`
- and :data:`sys.stderr`.
+ .. c:member:: int safe_path
- Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSSTDIO` environment
- variable is set to a non-empty string.
+ If equals to zero, ``Py_RunMain()`` prepends a potentially unsafe path to
+ :data:`sys.path` at startup:
- Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
- Windows specific code.
+ * If :c:member:`argv[0] <PyConfig.argv>` is equal to ``L"-m"``
+ (``python -m module``), prepend the current working directory.
+ * If running a script (``python script.py``), prepend the script's
+ directory. If it's a symbolic link, resolve symbolic links.
+ * Otherwise (``python -c code`` and ``python``), prepend an empty string,
+ which means the current working directory.
- Default: ``0``.
+ Set to ``1`` by the :option:`-P` command line option and the
+ :envvar:`PYTHONSAFEPATH` environment variable.
- See also the :pep:`528` (Change Windows console encoding to UTF-8).
+ Default: ``0`` in Python config, ``1`` in isolated config.
- .. c:member:: int malloc_stats
+ .. versionadded:: 3.11
- If non-zero, dump statistics on :ref:`Python pymalloc memory allocator
- <pymalloc>` at exit.
+ .. c:member:: wchar_t* base_exec_prefix
- Set to ``1`` by the :envvar:`PYTHONMALLOCSTATS` environment variable.
+ :data:`sys.base_exec_prefix`.
- The option is ignored if Python is :option:`configured using
- the --without-pymalloc option <--without-pymalloc>`.
+ Default: ``NULL``.
- Default: ``0``.
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
- .. c:member:: wchar_t* platlibdir
+ See also :c:member:`PyConfig.exec_prefix`.
- Platform library directory name: :data:`sys.platlibdir`.
+ .. c:member:: wchar_t* base_executable
- Set by the :envvar:`PYTHONPLATLIBDIR` environment variable.
+ Python base executable: :data:`sys._base_executable`.
- Default: value of the ``PLATLIBDIR`` macro which is set by the
- :option:`configure --with-platlibdir option <--with-platlibdir>`
- (default: ``"lib"``, or ``"DLLs"`` on Windows).
+ Set by the :envvar:`__PYVENV_LAUNCHER__` environment variable.
- Part of the :ref:`Python Path Configuration <init-path-config>` input.
+ Set from :c:member:`PyConfig.executable` if ``NULL``.
- .. versionadded:: 3.9
+ Default: ``NULL``.
- .. versionchanged:: 3.11
- This macro is now used on Windows to locate the standard
- library extension modules, typically under ``DLLs``. However,
- for compatibility, note that this value is ignored for any
- non-standard layouts, including in-tree builds and virtual
- environments.
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
- .. c:member:: wchar_t* pythonpath_env
+ See also :c:member:`PyConfig.executable`.
- Module search paths (:data:`sys.path`) as a string separated by ``DELIM``
- (:data:`os.pathsep`).
+ .. c:member:: wchar_t* base_prefix
- Set by the :envvar:`PYTHONPATH` environment variable.
+ :data:`sys.base_prefix`.
Default: ``NULL``.
- Part of the :ref:`Python Path Configuration <init-path-config>` input.
-
- .. c:member:: PyWideStringList module_search_paths
- .. c:member:: int module_search_paths_set
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
- Module search paths: :data:`sys.path`.
+ See also :c:member:`PyConfig.prefix`.
- If :c:member:`~PyConfig.module_search_paths_set` is equal to ``0``,
- :c:func:`Py_InitializeFromConfig` will replace
- :c:member:`~PyConfig.module_search_paths` and sets
- :c:member:`~PyConfig.module_search_paths_set` to ``1``.
+ .. c:member:: int buffered_stdio
- Default: empty list (``module_search_paths``) and ``0``
- (``module_search_paths_set``).
+ If equals to ``0`` and :c:member:`~PyConfig.configure_c_stdio` is non-zero,
+ disable buffering on the C streams stdout and stderr.
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+ Set to ``0`` by the :option:`-u` command line option and the
+ :envvar:`PYTHONUNBUFFERED` environment variable.
- .. c:member:: int optimization_level
+ stdin is always opened in buffered mode.
- Compilation optimization level:
+ Default: ``1``.
- * ``0``: Peephole optimizer, set ``__debug__`` to ``True``.
- * ``1``: Level 0, remove assertions, set ``__debug__`` to ``False``.
- * ``2``: Level 1, strip docstrings.
+ .. c:member:: int bytes_warning
- Incremented by the :option:`-O` command line option. Set to the
- :envvar:`PYTHONOPTIMIZE` environment variable value.
+ If equals to ``1``, issue a warning when comparing :class:`bytes` or
+ :class:`bytearray` with :class:`str`, or comparing :class:`bytes` with
+ :class:`int`.
- Default: ``0``.
+ If equal or greater to ``2``, raise a :exc:`BytesWarning` exception in these
+ cases.
- .. c:member:: PyWideStringList orig_argv
+ Incremented by the :option:`-b` command line option.
- The list of the original command line arguments passed to the Python
- executable: :data:`sys.orig_argv`.
+ Default: ``0``.
- If :c:member:`~PyConfig.orig_argv` list is empty and
- :c:member:`~PyConfig.argv` is not a list only containing an empty
- string, :c:func:`PyConfig_Read` copies :c:member:`~PyConfig.argv` into
- :c:member:`~PyConfig.orig_argv` before modifying
- :c:member:`~PyConfig.argv` (if :c:member:`~PyConfig.parse_argv` is
- non-zero).
+ .. c:member:: int warn_default_encoding
- See also the :c:member:`~PyConfig.argv` member and the
- :c:func:`Py_GetArgcArgv` function.
+ If non-zero, emit a :exc:`EncodingWarning` warning when :class:`io.TextIOWrapper`
+ uses its default encoding. See :ref:`io-encoding-warning` for details.
- Default: empty list.
+ Default: ``0``.
.. versionadded:: 3.10
- .. c:member:: int parse_argv
+ .. c:member:: int code_debug_ranges
- Parse command line arguments?
+ If equals to ``0``, disables the inclusion of the end line and column
+ mappings in code objects. Also disables traceback printing carets to
+ specific error locations.
- If equals to ``1``, parse :c:member:`~PyConfig.argv` the same way the regular
- Python parses :ref:`command line arguments <using-on-cmdline>`, and strip
- Python arguments from :c:member:`~PyConfig.argv`.
+ Set to ``0`` by the :envvar:`PYTHONNODEBUGRANGES` environment variable
+ and by the :option:`-X no_debug_ranges <-X>` command line option.
- The :c:func:`PyConfig_Read` function only parses
- :c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv`
- is set to ``2`` after arguments are parsed. Since Python arguments are
- stripped from :c:member:`PyConfig.argv`, parsing arguments twice would
- parse the application options as Python options.
+ Default: ``1``.
- Default: ``1`` in Python mode, ``0`` in isolated mode.
+ .. versionadded:: 3.11
- .. versionchanged:: 3.10
- The :c:member:`PyConfig.argv` arguments are now only parsed if
- :c:member:`PyConfig.parse_argv` equals to ``1``.
+ .. c:member:: wchar_t* check_hash_pycs_mode
- .. c:member:: int parser_debug
+ Control the validation behavior of hash-based ``.pyc`` files:
+ value of the :option:`--check-hash-based-pycs` command line option.
- Parser debug mode. If greater than ``0``, turn on parser debugging output (for expert only, depending
- on compilation options).
+ Valid values:
- Incremented by the :option:`-d` command line option. Set to the
- :envvar:`PYTHONDEBUG` environment variable value.
+ - ``L"always"``: Hash the source file for invalidation regardless of
+ value of the 'check_source' flag.
+ - ``L"never"``: Assume that hash-based pycs always are valid.
+ - ``L"default"``: The 'check_source' flag in hash-based pycs
+ determines invalidation.
- Needs a :ref:`debug build of Python <debug-build>` (the ``Py_DEBUG`` macro
- must be defined).
+ Default: ``L"default"``.
- Default: ``0``.
+ See also :pep:`552` "Deterministic pycs".
- .. c:member:: int pathconfig_warnings
-
- If non-zero, calculation of path configuration is allowed to log
- warnings into ``stderr``. If equals to ``0``, suppress these warnings.
-
- Default: ``1`` in Python mode, ``0`` in isolated mode.
-
- Part of the :ref:`Python Path Configuration <init-path-config>` input.
+ .. c:member:: int configure_c_stdio
- .. versionchanged:: 3.11
- Now also applies on Windows.
+ If non-zero, configure C standard streams:
- .. c:member:: wchar_t* prefix
+ * On Windows, set the binary mode (``O_BINARY``) on stdin, stdout and
+ stderr.
+ * If :c:member:`~PyConfig.buffered_stdio` equals zero, disable buffering
+ of stdin, stdout and stderr streams.
+ * If :c:member:`~PyConfig.interactive` is non-zero, enable stream
+ buffering on stdin and stdout (only stdout on Windows).
- The site-specific directory prefix where the platform independent Python
- files are installed: :data:`sys.prefix`.
+ Default: ``1`` in Python config, ``0`` in isolated config.
- Default: ``NULL``.
+ .. c:member:: int dev_mode
- Part of the :ref:`Python Path Configuration <init-path-config>` output.
+ If non-zero, enable the :ref:`Python Development Mode <devmode>`.
- See also :c:member:`PyConfig.base_prefix`.
+ Set to ``1`` by the :option:`-X dev <-X>` option and the
+ :envvar:`PYTHONDEVMODE` environment variable.
- .. c:member:: wchar_t* program_name
+ Default: ``-1`` in Python mode, ``0`` in isolated mode.
- Program name used to initialize :c:member:`~PyConfig.executable` and in
- early error messages during Python initialization.
+ .. c:member:: int dump_refs
- * On macOS, use :envvar:`PYTHONEXECUTABLE` environment variable if set.
- * If the ``WITH_NEXT_FRAMEWORK`` macro is defined, use
- :envvar:`__PYVENV_LAUNCHER__` environment variable if set.
- * Use ``argv[0]`` of :c:member:`~PyConfig.argv` if available and
- non-empty.
- * Otherwise, use ``L"python"`` on Windows, or ``L"python3"`` on other
- platforms.
+ Dump Python references?
- Default: ``NULL``.
+ If non-zero, dump all objects which are still alive at exit.
- Part of the :ref:`Python Path Configuration <init-path-config>` input.
+ Set to ``1`` by the :envvar:`PYTHONDUMPREFS` environment variable.
- .. c:member:: wchar_t* pycache_prefix
+ Needs a special build of Python with the ``Py_TRACE_REFS`` macro defined:
+ see the :option:`configure --with-trace-refs option <--with-trace-refs>`.
- Directory where cached ``.pyc`` files are written:
- :data:`sys.pycache_prefix`.
+ Default: ``0``.
- Set by the :option:`-X pycache_prefix=PATH <-X>` command line option and
- the :envvar:`PYTHONPYCACHEPREFIX` environment variable.
- The command-line option takes precedence.
+ .. c:member:: wchar_t* exec_prefix
- If ``NULL``, :data:`sys.pycache_prefix` is set to ``None``.
+ The site-specific directory prefix where the platform-dependent Python
+ files are installed: :data:`sys.exec_prefix`.
Default: ``NULL``.
- .. c:member:: int quiet
-
- Quiet mode. If greater than ``0``, don't display the copyright and version at
- Python startup in interactive mode.
-
- Incremented by the :option:`-q` command line option.
-
- Default: ``0``.
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
- .. c:member:: wchar_t* run_command
+ See also :c:member:`PyConfig.base_exec_prefix`.
- Value of the :option:`-c` command line option.
+ .. c:member:: wchar_t* executable
- Used by :c:func:`Py_RunMain`.
+ The absolute path of the executable binary for the Python interpreter:
+ :data:`sys.executable`.
Default: ``NULL``.
- .. c:member:: wchar_t* run_filename
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
- Filename passed on the command line: trailing command line argument
- without :option:`-c` or :option:`-m`. It is used by the
- :c:func:`Py_RunMain` function.
+ See also :c:member:`PyConfig.base_executable`.
- For example, it is set to ``script.py`` by the ``python3 script.py arg``
- command line.
+ .. c:member:: int faulthandler
- See also the :c:member:`PyConfig.skip_source_first_line` option.
+ Enable faulthandler?
- Default: ``NULL``.
+ If non-zero, call :func:`faulthandler.enable` at startup.
- .. c:member:: wchar_t* run_module
+ Set to ``1`` by :option:`-X faulthandler <-X>` and the
+ :envvar:`PYTHONFAULTHANDLER` environment variable.
- Value of the :option:`-m` command line option.
+ Default: ``-1`` in Python mode, ``0`` in isolated mode.
- Used by :c:func:`Py_RunMain`.
+ .. c:member:: wchar_t* filesystem_encoding
- Default: ``NULL``.
+ :term:`Filesystem encoding <filesystem encoding and error handler>`:
+ :func:`sys.getfilesystemencoding`.
- .. c:member:: wchar_t* run_presite
+ On macOS, Android and VxWorks: use ``"utf-8"`` by default.
- ``package.module`` path to module that should be imported before
- ``site.py`` is run.
+ On Windows: use ``"utf-8"`` by default, or ``"mbcs"`` if
+ :c:member:`~PyPreConfig.legacy_windows_fs_encoding` of
+ :c:type:`PyPreConfig` is non-zero.
- Set by the :option:`-X presite=package.module <-X>` command-line
- option and the :envvar:`PYTHON_PRESITE` environment variable.
- The command-line option takes precedence.
+ Default encoding on other platforms:
- Needs a :ref:`debug build of Python <debug-build>` (the ``Py_DEBUG`` macro
- must be defined).
+ * ``"utf-8"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero.
+ * ``"ascii"`` if Python detects that ``nl_langinfo(CODESET)`` announces
+ the ASCII encoding, whereas the ``mbstowcs()`` function
+ decodes from a different encoding (usually Latin1).
+ * ``"utf-8"`` if ``nl_langinfo(CODESET)`` returns an empty string.
+ * Otherwise, use the :term:`locale encoding`:
+ ``nl_langinfo(CODESET)`` result.
- Default: ``NULL``.
+ At Python startup, the encoding name is normalized to the Python codec
+ name. For example, ``"ANSI_X3.4-1968"`` is replaced with ``"ascii"``.
- .. c:member:: int show_ref_count
+ See also the :c:member:`~PyConfig.filesystem_errors` member.
- Show total reference count at exit (excluding :term:`immortal` objects)?
+ .. c:member:: wchar_t* filesystem_errors
- Set to ``1`` by :option:`-X showrefcount <-X>` command line option.
+ :term:`Filesystem error handler <filesystem encoding and error handler>`:
+ :func:`sys.getfilesystemencodeerrors`.
- Needs a :ref:`debug build of Python <debug-build>` (the ``Py_REF_DEBUG``
- macro must be defined).
+ On Windows: use ``"surrogatepass"`` by default, or ``"replace"`` if
+ :c:member:`~PyPreConfig.legacy_windows_fs_encoding` of
+ :c:type:`PyPreConfig` is non-zero.
- Default: ``0``.
+ On other platforms: use ``"surrogateescape"`` by default.
- .. c:member:: int site_import
+ Supported error handlers:
- Import the :mod:`site` module at startup?
+ * ``"strict"``
+ * ``"surrogateescape"``
+ * ``"surrogatepass"`` (only supported with the UTF-8 encoding)
- If equal to zero, disable the import of the module site and the
- site-dependent manipulations of :data:`sys.path` that it entails.
+ See also the :c:member:`~PyConfig.filesystem_encoding` member.
- Also disable these manipulations if the :mod:`site` module is explicitly
- imported later (call :func:`site.main` if you want them to be triggered).
+ .. c:member:: unsigned long hash_seed
+ .. c:member:: int use_hash_seed
- Set to ``0`` by the :option:`-S` command line option.
+ Randomized hash function seed.
- :data:`sys.flags.no_site <sys.flags>` is set to the inverted value of
- :c:member:`~PyConfig.site_import`.
+ If :c:member:`~PyConfig.use_hash_seed` is zero, a seed is chosen randomly
+ at Python startup, and :c:member:`~PyConfig.hash_seed` is ignored.
- Default: ``1``.
+ Set by the :envvar:`PYTHONHASHSEED` environment variable.
- .. c:member:: int skip_source_first_line
+ Default *use_hash_seed* value: ``-1`` in Python mode, ``0`` in isolated
+ mode.
- If non-zero, skip the first line of the :c:member:`PyConfig.run_filename`
- source.
+ .. c:member:: wchar_t* home
- It allows the usage of non-Unix forms of ``#!cmd``. This is intended for
- a DOS specific hack only.
+ Set the default Python "home" directory, that is, the location of the
+ standard Python libraries (see :envvar:`PYTHONHOME`).
- Set to ``1`` by the :option:`-x` command line option.
+ Set by the :envvar:`PYTHONHOME` environment variable.
- Default: ``0``.
+ Default: ``NULL``.
- .. c:member:: wchar_t* stdio_encoding
- .. c:member:: wchar_t* stdio_errors
+ Part of the :ref:`Python Path Configuration <init-path-config>` input.
- Encoding and encoding errors of :data:`sys.stdin`, :data:`sys.stdout` and
- :data:`sys.stderr` (but :data:`sys.stderr` always uses
- ``"backslashreplace"`` error handler).
+ .. c:member:: int import_time
- Use the :envvar:`PYTHONIOENCODING` environment variable if it is
- non-empty.
+ If non-zero, profile import time.
- Default encoding:
+ Set the ``1`` by the :option:`-X importtime <-X>` option and the
+ :envvar:`PYTHONPROFILEIMPORTTIME` environment variable.
- * ``"UTF-8"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero.
- * Otherwise, use the :term:`locale encoding`.
+ Default: ``0``.
- Default error handler:
+ .. c:member:: int inspect
- * On Windows: use ``"surrogateescape"``.
- * ``"surrogateescape"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero,
- or if the LC_CTYPE locale is "C" or "POSIX".
- * ``"strict"`` otherwise.
+ Enter interactive mode after executing a script or a command.
- See also :c:member:`PyConfig.legacy_windows_stdio`.
+ If greater than ``0``, enable inspect: when a script is passed as first
+ argument or the -c option is used, enter interactive mode after executing
+ the script or the command, even when :data:`sys.stdin` does not appear to
+ be a terminal.
- .. c:member:: int tracemalloc
+ Incremented by the :option:`-i` command line option. Set to ``1`` if the
+ :envvar:`PYTHONINSPECT` environment variable is non-empty.
- Enable tracemalloc?
+ Default: ``0``.
- If non-zero, call :func:`tracemalloc.start` at startup.
+ .. c:member:: int install_signal_handlers
- Set by :option:`-X tracemalloc=N <-X>` command line option and by the
- :envvar:`PYTHONTRACEMALLOC` environment variable.
+ Install Python signal handlers?
- Default: ``-1`` in Python mode, ``0`` in isolated mode.
+ Default: ``1`` in Python mode, ``0`` in isolated mode.
- .. c:member:: int perf_profiling
+ .. c:member:: int interactive
- Enable the Linux ``perf`` profiler support?
+ If greater than ``0``, enable the interactive mode (REPL).
- If equals to ``1``, enable support for the Linux ``perf`` profiler.
+ Incremented by the :option:`-i` command line option.
- If equals to ``2``, enable support for the Linux ``perf`` profiler with
- DWARF JIT support.
+ Default: ``0``.
- Set to ``1`` by :option:`-X perf <-X>` command-line option and the
- :envvar:`PYTHONPERFSUPPORT` environment variable.
+ .. c:member:: int int_max_str_digits
- Set to ``2`` by the :option:`-X perf_jit <-X>` command-line option and
- the :envvar:`PYTHON_PERF_JIT_SUPPORT` environment variable.
+ Configures the :ref:`integer string conversion length limitation
+ <int_max_str_digits>`. An initial value of ``-1`` means the value will
+ be taken from the command line or environment or otherwise default to
+ 4300 (:data:`sys.int_info.default_max_str_digits`). A value of ``0``
+ disables the limitation. Values greater than zero but less than 640
+ (:data:`sys.int_info.str_digits_check_threshold`) are unsupported and
+ will produce an error.
- Default: ``-1``.
+ Configured by the :option:`-X int_max_str_digits <-X>` command line
+ flag or the :envvar:`PYTHONINTMAXSTRDIGITS` environment variable.
- .. seealso::
- See :ref:`perf_profiling` for more information.
+ Default: ``-1`` in Python mode. 4300
+ (:data:`sys.int_info.default_max_str_digits`) in isolated mode.
.. versionadded:: 3.12
- .. c:member:: int use_environment
+ .. c:member:: int cpu_count
- Use :ref:`environment variables <using-on-envvars>`?
+ If the value of :c:member:`~PyConfig.cpu_count` is not ``-1`` then it will
+ override the return values of :func:`os.cpu_count`,
+ :func:`os.process_cpu_count`, and :func:`multiprocessing.cpu_count`.
- If equals to zero, ignore the :ref:`environment variables
- <using-on-envvars>`.
+ Configured by the :samp:`-X cpu_count={n|default}` command line
+ flag or the :envvar:`PYTHON_CPU_COUNT` environment variable.
- Set to ``0`` by the :option:`-E` environment variable.
+ Default: ``-1``.
- Default: ``1`` in Python config and ``0`` in isolated config.
+ .. versionadded:: 3.13
- .. c:member:: int use_system_logger
+ .. c:member:: int isolated
- If non-zero, ``stdout`` and ``stderr`` will be redirected to the system
- log.
+ If greater than ``0``, enable isolated mode:
- Only available on macOS 10.12 and later, and on iOS.
+ * Set :c:member:`~PyConfig.safe_path` to ``1``:
+ don't prepend a potentially unsafe path to :data:`sys.path` at Python
+ startup, such as the current directory, the script's directory or an
+ empty string.
+ * Set :c:member:`~PyConfig.use_environment` to ``0``: ignore ``PYTHON``
+ environment variables.
+ * Set :c:member:`~PyConfig.user_site_directory` to ``0``: don't add the user
+ site directory to :data:`sys.path`.
+ * Python REPL doesn't import :mod:`readline` nor enable default readline
+ configuration on interactive prompts.
- Default: ``0`` (don't use system log).
+ Set to ``1`` by the :option:`-I` command line option.
- .. versionadded:: 3.13.2
+ Default: ``0`` in Python mode, ``1`` in isolated mode.
- .. c:member:: int user_site_directory
+ See also the :ref:`Isolated Configuration <init-isolated-conf>` and
+ :c:member:`PyPreConfig.isolated`.
- If non-zero, add the user site directory to :data:`sys.path`.
+ .. c:member:: int legacy_windows_stdio
- Set to ``0`` by the :option:`-s` and :option:`-I` command line options.
+ If non-zero, use :class:`io.FileIO` instead of
+ :class:`!io._WindowsConsoleIO` for :data:`sys.stdin`, :data:`sys.stdout`
+ and :data:`sys.stderr`.
- Set to ``0`` by the :envvar:`PYTHONNOUSERSITE` environment variable.
+ Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSSTDIO` environment
+ variable is set to a non-empty string.
- Default: ``1`` in Python mode, ``0`` in isolated mode.
+ Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
+ Windows specific code.
- .. c:member:: int verbose
+ Default: ``0``.
- Verbose mode. If greater than ``0``, print a message each time a module is
- imported, showing the place (filename or built-in module) from which
- it is loaded.
+ See also the :pep:`528` (Change Windows console encoding to UTF-8).
- If greater than or equal to ``2``, print a message for each file that is
- checked for when searching for a module. Also provides information on
- module cleanup at exit.
+ .. c:member:: int malloc_stats
- Incremented by the :option:`-v` command line option.
+ If non-zero, dump statistics on :ref:`Python pymalloc memory allocator
+ <pymalloc>` at exit.
- Set by the :envvar:`PYTHONVERBOSE` environment variable value.
+ Set to ``1`` by the :envvar:`PYTHONMALLOCSTATS` environment variable.
+
+ The option is ignored if Python is :option:`configured using
+ the --without-pymalloc option <--without-pymalloc>`.
Default: ``0``.
- .. c:member:: PyWideStringList warnoptions
+ .. c:member:: wchar_t* platlibdir
- Options of the :mod:`warnings` module to build warnings filters, lowest
- to highest priority: :data:`sys.warnoptions`.
+ Platform library directory name: :data:`sys.platlibdir`.
- The :mod:`warnings` module adds :data:`sys.warnoptions` in the reverse
- order: the last :c:member:`PyConfig.warnoptions` item becomes the first
- item of :data:`warnings.filters` which is checked first (highest
- priority).
+ Set by the :envvar:`PYTHONPLATLIBDIR` environment variable.
- The :option:`-W` command line options adds its value to
- :c:member:`~PyConfig.warnoptions`, it can be used multiple times.
+ Default: value of the ``PLATLIBDIR`` macro which is set by the
+ :option:`configure --with-platlibdir option <--with-platlibdir>`
+ (default: ``"lib"``, or ``"DLLs"`` on Windows).
- The :envvar:`PYTHONWARNINGS` environment variable can also be used to add
- warning options. Multiple options can be specified, separated by commas
- (``,``).
+ Part of the :ref:`Python Path Configuration <init-path-config>` input.
- Default: empty list.
+ .. versionadded:: 3.9
- .. c:member:: int write_bytecode
+ .. versionchanged:: 3.11
+ This macro is now used on Windows to locate the standard
+ library extension modules, typically under ``DLLs``. However,
+ for compatibility, note that this value is ignored for any
+ non-standard layouts, including in-tree builds and virtual
+ environments.
- If equal to ``0``, Python won't try to write ``.pyc`` files on the import of
- source modules.
+ .. c:member:: wchar_t* pythonpath_env
- Set to ``0`` by the :option:`-B` command line option and the
- :envvar:`PYTHONDONTWRITEBYTECODE` environment variable.
+ Module search paths (:data:`sys.path`) as a string separated by ``DELIM``
+ (:data:`os.pathsep`).
- :data:`sys.dont_write_bytecode` is initialized to the inverted value of
- :c:member:`~PyConfig.write_bytecode`.
+ Set by the :envvar:`PYTHONPATH` environment variable.
- Default: ``1``.
+ Default: ``NULL``.
- .. c:member:: PyWideStringList xoptions
+ Part of the :ref:`Python Path Configuration <init-path-config>` input.
- Values of the :option:`-X` command line options: :data:`sys._xoptions`.
+ .. c:member:: PyWideStringList module_search_paths
+ .. c:member:: int module_search_paths_set
- Default: empty list.
+ Module search paths: :data:`sys.path`.
-If :c:member:`~PyConfig.parse_argv` is non-zero, :c:member:`~PyConfig.argv`
-arguments are parsed the same way the regular Python parses :ref:`command line
-arguments <using-on-cmdline>`, and Python arguments are stripped from
-:c:member:`~PyConfig.argv`.
+ If :c:member:`~PyConfig.module_search_paths_set` is equal to ``0``,
+ :c:func:`Py_InitializeFromConfig` will replace
+ :c:member:`~PyConfig.module_search_paths` and sets
+ :c:member:`~PyConfig.module_search_paths_set` to ``1``.
-The :c:member:`~PyConfig.xoptions` options are parsed to set other options: see
-the :option:`-X` command line option.
+ Default: empty list (``module_search_paths``) and ``0``
+ (``module_search_paths_set``).
-.. versionchanged:: 3.9
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
- The ``show_alloc_count`` field has been removed.
+ .. c:member:: int optimization_level
+ Compilation optimization level:
-.. _init-from-config:
+ * ``0``: Peephole optimizer, set ``__debug__`` to ``True``.
+ * ``1``: Level 0, remove assertions, set ``__debug__`` to ``False``.
+ * ``2``: Level 1, strip docstrings.
-Initialization with PyConfig
-----------------------------
+ Incremented by the :option:`-O` command line option. Set to the
+ :envvar:`PYTHONOPTIMIZE` environment variable value.
-Initializing the interpreter from a populated configuration struct is handled
-by calling :c:func:`Py_InitializeFromConfig`.
+ Default: ``0``.
-The caller is responsible to handle exceptions (error or exit) using
-:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`.
+ .. c:member:: PyWideStringList orig_argv
-If :c:func:`PyImport_FrozenModules`, :c:func:`PyImport_AppendInittab` or
-:c:func:`PyImport_ExtendInittab` are used, they must be set or called after
-Python preinitialization and before the Python initialization. If Python is
-initialized multiple times, :c:func:`PyImport_AppendInittab` or
-:c:func:`PyImport_ExtendInittab` must be called before each Python
-initialization.
+ The list of the original command line arguments passed to the Python
+ executable: :data:`sys.orig_argv`.
-The current configuration (``PyConfig`` type) is stored in
-``PyInterpreterState.config``.
+ If :c:member:`~PyConfig.orig_argv` list is empty and
+ :c:member:`~PyConfig.argv` is not a list only containing an empty
+ string, :c:func:`PyConfig_Read` copies :c:member:`~PyConfig.argv` into
+ :c:member:`~PyConfig.orig_argv` before modifying
+ :c:member:`~PyConfig.argv` (if :c:member:`~PyConfig.parse_argv` is
+ non-zero).
-Example setting the program name::
+ See also the :c:member:`~PyConfig.argv` member and the
+ :c:func:`Py_GetArgcArgv` function.
- void init_python(void)
- {
- PyStatus status;
+ Default: empty list.
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
+ .. versionadded:: 3.10
- /* Set the program name. Implicitly preinitialize Python. */
- status = PyConfig_SetString(&config, &config.program_name,
- L"/path/to/my_program");
- if (PyStatus_Exception(status)) {
- goto exception;
- }
+ .. c:member:: int parse_argv
- status = Py_InitializeFromConfig(&config);
- if (PyStatus_Exception(status)) {
- goto exception;
- }
- PyConfig_Clear(&config);
- return;
+ Parse command line arguments?
- exception:
- PyConfig_Clear(&config);
- Py_ExitStatusException(status);
- }
+ If equals to ``1``, parse :c:member:`~PyConfig.argv` the same way the regular
+ Python parses :ref:`command line arguments <using-on-cmdline>`, and strip
+ Python arguments from :c:member:`~PyConfig.argv`.
-More complete example modifying the default configuration, read the
-configuration, and then override some parameters. Note that since
-3.11, many parameters are not calculated until initialization, and
-so values cannot be read from the configuration structure. Any values
-set before initialize is called will be left unchanged by
-initialization::
+ The :c:func:`PyConfig_Read` function only parses
+ :c:member:`PyConfig.argv` arguments once: :c:member:`PyConfig.parse_argv`
+ is set to ``2`` after arguments are parsed. Since Python arguments are
+ stripped from :c:member:`PyConfig.argv`, parsing arguments twice would
+ parse the application options as Python options.
- PyStatus init_python(const char *program_name)
- {
- PyStatus status;
+ Default: ``1`` in Python mode, ``0`` in isolated mode.
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
+ .. versionchanged:: 3.10
+ The :c:member:`PyConfig.argv` arguments are now only parsed if
+ :c:member:`PyConfig.parse_argv` equals to ``1``.
- /* Set the program name before reading the configuration
- (decode byte string from the locale encoding).
+ .. c:member:: int parser_debug
- Implicitly preinitialize Python. */
- status = PyConfig_SetBytesString(&config, &config.program_name,
- program_name);
- if (PyStatus_Exception(status)) {
- goto done;
- }
+ Parser debug mode. If greater than ``0``, turn on parser debugging output (for expert only, depending
+ on compilation options).
- /* Read all configuration at once */
- status = PyConfig_Read(&config);
- if (PyStatus_Exception(status)) {
- goto done;
- }
+ Incremented by the :option:`-d` command line option. Set to the
+ :envvar:`PYTHONDEBUG` environment variable value.
- /* Specify sys.path explicitly */
- /* If you want to modify the default set of paths, finish
- initialization first and then use PySys_GetObject("path") */
- config.module_search_paths_set = 1;
- status = PyWideStringList_Append(&config.module_search_paths,
- L"/path/to/stdlib");
- if (PyStatus_Exception(status)) {
- goto done;
- }
- status = PyWideStringList_Append(&config.module_search_paths,
- L"/path/to/more/modules");
- if (PyStatus_Exception(status)) {
- goto done;
- }
+ Needs a :ref:`debug build of Python <debug-build>` (the ``Py_DEBUG`` macro
+ must be defined).
- /* Override executable computed by PyConfig_Read() */
- status = PyConfig_SetString(&config, &config.executable,
- L"/path/to/my_executable");
- if (PyStatus_Exception(status)) {
- goto done;
- }
+ Default: ``0``.
- status = Py_InitializeFromConfig(&config);
+ .. c:member:: int pathconfig_warnings
- done:
- PyConfig_Clear(&config);
- return status;
- }
+ If non-zero, calculation of path configuration is allowed to log
+ warnings into ``stderr``. If equals to ``0``, suppress these warnings.
+ Default: ``1`` in Python mode, ``0`` in isolated mode.
-.. _init-isolated-conf:
+ Part of the :ref:`Python Path Configuration <init-path-config>` input.
-Isolated Configuration
-----------------------
+ .. versionchanged:: 3.11
+ Now also applies on Windows.
-:c:func:`PyPreConfig_InitIsolatedConfig` and
-:c:func:`PyConfig_InitIsolatedConfig` functions create a configuration to
-isolate Python from the system. For example, to embed Python into an
-application.
+ .. c:member:: wchar_t* prefix
-This configuration ignores global configuration variables, environment
-variables, command line arguments (:c:member:`PyConfig.argv` is not parsed)
-and user site directory. The C standard streams (ex: ``stdout``) and the
-LC_CTYPE locale are left unchanged. Signal handlers are not installed.
-
-Configuration files are still used with this configuration to determine
-paths that are unspecified. Ensure :c:member:`PyConfig.home` is specified
-to avoid computing the default path configuration.
+ The site-specific directory prefix where the platform independent Python
+ files are installed: :data:`sys.prefix`.
+ Default: ``NULL``.
-.. _init-python-config:
+ Part of the :ref:`Python Path Configuration <init-path-config>` output.
-Python Configuration
---------------------
+ See also :c:member:`PyConfig.base_prefix`.
-:c:func:`PyPreConfig_InitPythonConfig` and :c:func:`PyConfig_InitPythonConfig`
-functions create a configuration to build a customized Python which behaves as
-the regular Python.
+ .. c:member:: wchar_t* program_name
-Environments variables and command line arguments are used to configure
-Python, whereas global configuration variables are ignored.
+ Program name used to initialize :c:member:`~PyConfig.executable` and in
+ early error messages during Python initialization.
-This function enables C locale coercion (:pep:`538`)
-and :ref:`Python UTF-8 Mode <utf8-mode>`
-(:pep:`540`) depending on the LC_CTYPE locale, :envvar:`PYTHONUTF8` and
-:envvar:`PYTHONCOERCECLOCALE` environment variables.
+ * On macOS, use :envvar:`PYTHONEXECUTABLE` environment variable if set.
+ * If the ``WITH_NEXT_FRAMEWORK`` macro is defined, use
+ :envvar:`__PYVENV_LAUNCHER__` environment variable if set.
+ * Use ``argv[0]`` of :c:member:`~PyConfig.argv` if available and
+ non-empty.
+ * Otherwise, use ``L"python"`` on Windows, or ``L"python3"`` on other
+ platforms.
+ Default: ``NULL``.
-.. _init-path-config:
+ Part of the :ref:`Python Path Configuration <init-path-config>` input.
-Python Path Configuration
--------------------------
+ .. c:member:: wchar_t* pycache_prefix
-:c:type:`PyConfig` contains multiple fields for the path configuration:
+ Directory where cached ``.pyc`` files are written:
+ :data:`sys.pycache_prefix`.
-* Path configuration inputs:
+ Set by the :option:`-X pycache_prefix=PATH <-X>` command line option and
+ the :envvar:`PYTHONPYCACHEPREFIX` environment variable.
+ The command-line option takes precedence.
- * :c:member:`PyConfig.home`
- * :c:member:`PyConfig.platlibdir`
- * :c:member:`PyConfig.pathconfig_warnings`
- * :c:member:`PyConfig.program_name`
- * :c:member:`PyConfig.pythonpath_env`
- * current working directory: to get absolute paths
- * ``PATH`` environment variable to get the program full path
- (from :c:member:`PyConfig.program_name`)
- * ``__PYVENV_LAUNCHER__`` environment variable
- * (Windows only) Application paths in the registry under
- "Software\Python\PythonCore\X.Y\PythonPath" of HKEY_CURRENT_USER and
- HKEY_LOCAL_MACHINE (where X.Y is the Python version).
+ If ``NULL``, :data:`sys.pycache_prefix` is set to ``None``.
-* Path configuration output fields:
+ Default: ``NULL``.
- * :c:member:`PyConfig.base_exec_prefix`
- * :c:member:`PyConfig.base_executable`
- * :c:member:`PyConfig.base_prefix`
- * :c:member:`PyConfig.exec_prefix`
- * :c:member:`PyConfig.executable`
- * :c:member:`PyConfig.module_search_paths_set`,
- :c:member:`PyConfig.module_search_paths`
- * :c:member:`PyConfig.prefix`
+ .. c:member:: int quiet
-If at least one "output field" is not set, Python calculates the path
-configuration to fill unset fields. If
-:c:member:`~PyConfig.module_search_paths_set` is equal to ``0``,
-:c:member:`~PyConfig.module_search_paths` is overridden and
-:c:member:`~PyConfig.module_search_paths_set` is set to ``1``.
+ Quiet mode. If greater than ``0``, don't display the copyright and version at
+ Python startup in interactive mode.
-It is possible to completely ignore the function calculating the default
-path configuration by setting explicitly all path configuration output
-fields listed above. A string is considered as set even if it is non-empty.
-``module_search_paths`` is considered as set if
-``module_search_paths_set`` is set to ``1``. In this case,
-``module_search_paths`` will be used without modification.
+ Incremented by the :option:`-q` command line option.
-Set :c:member:`~PyConfig.pathconfig_warnings` to ``0`` to suppress warnings when
-calculating the path configuration (Unix only, Windows does not log any warning).
+ Default: ``0``.
-If :c:member:`~PyConfig.base_prefix` or :c:member:`~PyConfig.base_exec_prefix`
-fields are not set, they inherit their value from :c:member:`~PyConfig.prefix`
-and :c:member:`~PyConfig.exec_prefix` respectively.
+ .. c:member:: wchar_t* run_command
-:c:func:`Py_RunMain` and :c:func:`Py_Main` modify :data:`sys.path`:
+ Value of the :option:`-c` command line option.
-* If :c:member:`~PyConfig.run_filename` is set and is a directory which contains a
- ``__main__.py`` script, prepend :c:member:`~PyConfig.run_filename` to
- :data:`sys.path`.
-* If :c:member:`~PyConfig.isolated` is zero:
+ Used by :c:func:`Py_RunMain`.
- * If :c:member:`~PyConfig.run_module` is set, prepend the current directory
- to :data:`sys.path`. Do nothing if the current directory cannot be read.
- * If :c:member:`~PyConfig.run_filename` is set, prepend the directory of the
- filename to :data:`sys.path`.
- * Otherwise, prepend an empty string to :data:`sys.path`.
+ Default: ``NULL``.
-If :c:member:`~PyConfig.site_import` is non-zero, :data:`sys.path` can be
-modified by the :mod:`site` module. If
-:c:member:`~PyConfig.user_site_directory` is non-zero and the user's
-site-package directory exists, the :mod:`site` module appends the user's
-site-package directory to :data:`sys.path`.
+ .. c:member:: wchar_t* run_filename
-The following configuration files are used by the path configuration:
+ Filename passed on the command line: trailing command line argument
+ without :option:`-c` or :option:`-m`. It is used by the
+ :c:func:`Py_RunMain` function.
-* ``pyvenv.cfg``
-* ``._pth`` file (ex: ``python._pth``)
-* ``pybuilddir.txt`` (Unix only)
+ For example, it is set to ``script.py`` by the ``python3 script.py arg``
+ command line.
-If a ``._pth`` file is present:
+ See also the :c:member:`PyConfig.skip_source_first_line` option.
-* Set :c:member:`~PyConfig.isolated` to ``1``.
-* Set :c:member:`~PyConfig.use_environment` to ``0``.
-* Set :c:member:`~PyConfig.site_import` to ``0``.
-* Set :c:member:`~PyConfig.safe_path` to ``1``.
+ Default: ``NULL``.
-If :c:member:`~PyConfig.home` is not set and a ``pyvenv.cfg`` file is present in
-the same directory as :c:member:`~PyConfig.executable`, or its parent,
-:c:member:`~PyConfig.prefix` and :c:member:`~PyConfig.exec_prefix` are set that
-location. When this happens, :c:member:`~PyConfig.base_prefix` and
-:c:member:`~PyConfig.base_exec_prefix` still keep their value, pointing to the
-base installation. See :ref:`sys-path-init-virtual-environments` for more
-information.
+ .. c:member:: wchar_t* run_module
-The ``__PYVENV_LAUNCHER__`` environment variable is used to set
-:c:member:`PyConfig.base_executable`.
+ Value of the :option:`-m` command line option.
-.. versionchanged:: 3.14
+ Used by :c:func:`Py_RunMain`.
- :c:member:`~PyConfig.prefix`, and :c:member:`~PyConfig.exec_prefix`, are now
- set to the ``pyvenv.cfg`` directory. This was previously done by :mod:`site`,
- therefore affected by :option:`-S`.
+ Default: ``NULL``.
-.. _pyinitconfig_api:
+ .. c:member:: wchar_t* run_presite
-PyInitConfig C API
-==================
+ ``package.module`` path to module that should be imported before
+ ``site.py`` is run.
-C API to configure the Python initialization (:pep:`741`).
+ Set by the :option:`-X presite=package.module <-X>` command-line
+ option and the :envvar:`PYTHON_PRESITE` environment variable.
+ The command-line option takes precedence.
-.. versionadded:: 3.14
+ Needs a :ref:`debug build of Python <debug-build>` (the ``Py_DEBUG`` macro
+ must be defined).
-Create Config
--------------
+ Default: ``NULL``.
-.. c:struct:: PyInitConfig
+ .. c:member:: int show_ref_count
- Opaque structure to configure the Python initialization.
+ Show total reference count at exit (excluding :term:`immortal` objects)?
+ Set to ``1`` by :option:`-X showrefcount <-X>` command line option.
-.. c:function:: PyInitConfig* PyInitConfig_Create(void)
+ Needs a :ref:`debug build of Python <debug-build>` (the ``Py_REF_DEBUG``
+ macro must be defined).
- Create a new initialization configuration using :ref:`Isolated Configuration
- <init-isolated-conf>` default values.
+ Default: ``0``.
- It must be freed by :c:func:`PyInitConfig_Free`.
+ .. c:member:: int site_import
- Return ``NULL`` on memory allocation failure.
+ Import the :mod:`site` module at startup?
+ If equal to zero, disable the import of the module site and the
+ site-dependent manipulations of :data:`sys.path` that it entails.
-.. c:function:: void PyInitConfig_Free(PyInitConfig *config)
+ Also disable these manipulations if the :mod:`site` module is explicitly
+ imported later (call :func:`site.main` if you want them to be triggered).
- Free memory of the initialization configuration *config*.
+ Set to ``0`` by the :option:`-S` command line option.
- If *config* is ``NULL``, no operation is performed.
+ :data:`sys.flags.no_site <sys.flags>` is set to the inverted value of
+ :c:member:`~PyConfig.site_import`.
+ Default: ``1``.
-Error Handling
---------------
+ .. c:member:: int skip_source_first_line
-.. c:function:: int PyInitConfig_GetError(PyInitConfig* config, const char **err_msg)
+ If non-zero, skip the first line of the :c:member:`PyConfig.run_filename`
+ source.
- Get the *config* error message.
+ It allows the usage of non-Unix forms of ``#!cmd``. This is intended for
+ a DOS specific hack only.
- * Set *\*err_msg* and return ``1`` if an error is set.
- * Set *\*err_msg* to ``NULL`` and return ``0`` otherwise.
+ Set to ``1`` by the :option:`-x` command line option.
- An error message is an UTF-8 encoded string.
+ Default: ``0``.
- If *config* has an exit code, format the exit code as an error
- message.
+ .. c:member:: wchar_t* stdio_encoding
+ .. c:member:: wchar_t* stdio_errors
- The error message remains valid until another ``PyInitConfig``
- function is called with *config*. The caller doesn't have to free the
- error message.
+ Encoding and encoding errors of :data:`sys.stdin`, :data:`sys.stdout` and
+ :data:`sys.stderr` (but :data:`sys.stderr` always uses
+ ``"backslashreplace"`` error handler).
+ Use the :envvar:`PYTHONIOENCODING` environment variable if it is
+ non-empty.
-.. c:function:: int PyInitConfig_GetExitCode(PyInitConfig* config, int *exitcode)
+ Default encoding:
- Get the *config* exit code.
+ * ``"UTF-8"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero.
+ * Otherwise, use the :term:`locale encoding`.
- * Set *\*exitcode* and return ``1`` if *config* has an exit code set.
- * Return ``0`` if *config* has no exit code set.
+ Default error handler:
- Only the ``Py_InitializeFromInitConfig()`` function can set an exit
- code if the ``parse_argv`` option is non-zero.
+ * On Windows: use ``"surrogateescape"``.
+ * ``"surrogateescape"`` if :c:member:`PyPreConfig.utf8_mode` is non-zero,
+ or if the LC_CTYPE locale is "C" or "POSIX".
+ * ``"strict"`` otherwise.
- An exit code can be set when parsing the command line failed (exit
- code ``2``) or when a command line option asks to display the command
- line help (exit code ``0``).
+ See also :c:member:`PyConfig.legacy_windows_stdio`.
+ .. c:member:: int tracemalloc
-Get Options
------------
+ Enable tracemalloc?
-The configuration option *name* parameter must be a non-NULL
-null-terminated UTF-8 encoded string.
+ If non-zero, call :func:`tracemalloc.start` at startup.
-.. c:function:: int PyInitConfig_HasOption(PyInitConfig *config, const char *name)
+ Set by :option:`-X tracemalloc=N <-X>` command line option and by the
+ :envvar:`PYTHONTRACEMALLOC` environment variable.
- Test if the configuration has an option called *name*.
+ Default: ``-1`` in Python mode, ``0`` in isolated mode.
- Return ``1`` if the option exists, or return ``0`` otherwise.
+ .. c:member:: int perf_profiling
+ Enable the Linux ``perf`` profiler support?
-.. c:function:: int PyInitConfig_GetInt(PyInitConfig *config, const char *name, int64_t *value)
+ If equals to ``1``, enable support for the Linux ``perf`` profiler.
- Get an integer configuration option.
+ If equals to ``2``, enable support for the Linux ``perf`` profiler with
+ DWARF JIT support.
- * Set *\*value*, and return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ Set to ``1`` by :option:`-X perf <-X>` command-line option and the
+ :envvar:`PYTHONPERFSUPPORT` environment variable.
+ Set to ``2`` by the :option:`-X perf_jit <-X>` command-line option and
+ the :envvar:`PYTHON_PERF_JIT_SUPPORT` environment variable.
-.. c:function:: int PyInitConfig_GetStr(PyInitConfig *config, const char *name, char **value)
+ Default: ``-1``.
- Get a string configuration option as a null-terminated UTF-8
- encoded string.
+ .. seealso::
+ See :ref:`perf_profiling` for more information.
- * Set *\*value*, and return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ .. versionadded:: 3.12
- *\*value* can be set to ``NULL`` if the option is an optional string and the
- option is unset.
+ .. c:member:: int use_environment
- On success, the string must be released with ``free(value)`` if it's not
- ``NULL``.
+ Use :ref:`environment variables <using-on-envvars>`?
+ If equals to zero, ignore the :ref:`environment variables
+ <using-on-envvars>`.
-.. c:function:: int PyInitConfig_GetStrList(PyInitConfig *config, const char *name, size_t *length, char ***items)
+ Set to ``0`` by the :option:`-E` environment variable.
- Get a string list configuration option as an array of
- null-terminated UTF-8 encoded strings.
+ Default: ``1`` in Python config and ``0`` in isolated config.
- * Set *\*length* and *\*value*, and return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ .. c:member:: int use_system_logger
- On success, the string list must be released with
- ``PyInitConfig_FreeStrList(length, items)``.
+ If non-zero, ``stdout`` and ``stderr`` will be redirected to the system
+ log.
+ Only available on macOS 10.12 and later, and on iOS.
-.. c:function:: void PyInitConfig_FreeStrList(size_t length, char **items)
+ Default: ``0`` (don't use system log).
- Free memory of a string list created by
- ``PyInitConfig_GetStrList()``.
+ .. versionadded:: 3.13.2
+ .. c:member:: int user_site_directory
-Set Options
------------
+ If non-zero, add the user site directory to :data:`sys.path`.
-The configuration option *name* parameter must be a non-NULL null-terminated
-UTF-8 encoded string.
+ Set to ``0`` by the :option:`-s` and :option:`-I` command line options.
-Some configuration options have side effects on other options. This logic is
-only implemented when ``Py_InitializeFromInitConfig()`` is called, not by the
-"Set" functions below. For example, setting ``dev_mode`` to ``1`` does not set
-``faulthandler`` to ``1``.
+ Set to ``0`` by the :envvar:`PYTHONNOUSERSITE` environment variable.
-.. c:function:: int PyInitConfig_SetInt(PyInitConfig *config, const char *name, int64_t value)
+ Default: ``1`` in Python mode, ``0`` in isolated mode.
- Set an integer configuration option.
+ .. c:member:: int verbose
- * Return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ Verbose mode. If greater than ``0``, print a message each time a module is
+ imported, showing the place (filename or built-in module) from which
+ it is loaded.
+ If greater than or equal to ``2``, print a message for each file that is
+ checked for when searching for a module. Also provides information on
+ module cleanup at exit.
-.. c:function:: int PyInitConfig_SetStr(PyInitConfig *config, const char *name, const char *value)
+ Incremented by the :option:`-v` command line option.
- Set a string configuration option from a null-terminated UTF-8
- encoded string. The string is copied.
+ Set by the :envvar:`PYTHONVERBOSE` environment variable value.
- * Return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ Default: ``0``.
+ .. c:member:: PyWideStringList warnoptions
-.. c:function:: int PyInitConfig_SetStrList(PyInitConfig *config, const char *name, size_t length, char * const *items)
+ Options of the :mod:`warnings` module to build warnings filters, lowest
+ to highest priority: :data:`sys.warnoptions`.
- Set a string list configuration option from an array of
- null-terminated UTF-8 encoded strings. The string list is copied.
+ The :mod:`warnings` module adds :data:`sys.warnoptions` in the reverse
+ order: the last :c:member:`PyConfig.warnoptions` item becomes the first
+ item of :data:`warnings.filters` which is checked first (highest
+ priority).
- * Return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ The :option:`-W` command line options adds its value to
+ :c:member:`~PyConfig.warnoptions`, it can be used multiple times.
+ The :envvar:`PYTHONWARNINGS` environment variable can also be used to add
+ warning options. Multiple options can be specified, separated by commas
+ (``,``).
-Module
-------
+ Default: empty list.
-.. c:function:: int PyInitConfig_AddModule(PyInitConfig *config, const char *name, PyObject* (*initfunc)(void))
+ .. c:member:: int write_bytecode
- Add a built-in extension module to the table of built-in modules.
+ If equal to ``0``, Python won't try to write ``.pyc`` files on the import of
+ source modules.
- The new module can be imported by the name *name*, and uses the function
- *initfunc* as the initialization function called on the first attempted
- import.
+ Set to ``0`` by the :option:`-B` command line option and the
+ :envvar:`PYTHONDONTWRITEBYTECODE` environment variable.
- * Return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
+ :data:`sys.dont_write_bytecode` is initialized to the inverted value of
+ :c:member:`~PyConfig.write_bytecode`.
- If Python is initialized multiple times, ``PyInitConfig_AddModule()`` must
- be called at each Python initialization.
+ Default: ``1``.
- Similar to the :c:func:`PyImport_AppendInittab` function.
+ .. c:member:: PyWideStringList xoptions
+ Values of the :option:`-X` command line options: :data:`sys._xoptions`.
-Initialize Python
------------------
+ Default: empty list.
-.. c:function:: int Py_InitializeFromInitConfig(PyInitConfig *config)
+If :c:member:`~PyConfig.parse_argv` is non-zero, :c:member:`~PyConfig.argv`
+arguments are parsed the same way the regular Python parses :ref:`command line
+arguments <using-on-cmdline>`, and Python arguments are stripped from
+:c:member:`~PyConfig.argv`.
- Initialize Python from the initialization configuration.
+The :c:member:`~PyConfig.xoptions` options are parsed to set other options: see
+the :option:`-X` command line option.
- * Return ``0`` on success.
- * Set an error in *config* and return ``-1`` on error.
- * Set an exit code in *config* and return ``-1`` if Python wants to
- exit.
+.. versionchanged:: 3.9
- See ``PyInitConfig_GetExitcode()`` for the exit code case.
+ The ``show_alloc_count`` field has been removed.
-Example
--------
+.. _init-from-config:
-Example initializing Python, set configuration options of various types,
-return ``-1`` on error:
+Initialization with PyConfig
+----------------------------
-.. code-block:: c
+Initializing the interpreter from a populated configuration struct is handled
+by calling :c:func:`Py_InitializeFromConfig`.
- int init_python(void)
+The caller is responsible to handle exceptions (error or exit) using
+:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`.
+
+If :c:func:`PyImport_FrozenModules`, :c:func:`PyImport_AppendInittab` or
+:c:func:`PyImport_ExtendInittab` are used, they must be set or called after
+Python preinitialization and before the Python initialization. If Python is
+initialized multiple times, :c:func:`PyImport_AppendInittab` or
+:c:func:`PyImport_ExtendInittab` must be called before each Python
+initialization.
+
+The current configuration (``PyConfig`` type) is stored in
+``PyInterpreterState.config``.
+
+Example setting the program name::
+
+ void init_python(void)
{
- PyInitConfig *config = PyInitConfig_Create();
- if (config == NULL) {
- printf("PYTHON INIT ERROR: memory allocation failed\n");
- return -1;
- }
+ PyStatus status;
- // Set an integer (dev mode)
- if (PyInitConfig_SetInt(config, "dev_mode", 1) < 0) {
- goto error;
+ PyConfig config;
+ PyConfig_InitPythonConfig(&config);
+
+ /* Set the program name. Implicitly preinitialize Python. */
+ status = PyConfig_SetString(&config, &config.program_name,
+ L"/path/to/my_program");
+ if (PyStatus_Exception(status)) {
+ goto exception;
}
- // Set a list of UTF-8 strings (argv)
- char *argv[] = {"my_program", "-c", "pass"};
- if (PyInitConfig_SetStrList(config, "argv",
- Py_ARRAY_LENGTH(argv), argv) < 0) {
- goto error;
+ status = Py_InitializeFromConfig(&config);
+ if (PyStatus_Exception(status)) {
+ goto exception;
}
+ PyConfig_Clear(&config);
+ return;
- // Set a UTF-8 string (program name)
- if (PyInitConfig_SetStr(config, "program_name", L"my_program") < 0) {
- goto error;
+ exception:
+ PyConfig_Clear(&config);
+ Py_ExitStatusException(status);
+ }
+
+More complete example modifying the default configuration, read the
+configuration, and then override some parameters. Note that since
+3.11, many parameters are not calculated until initialization, and
+so values cannot be read from the configuration structure. Any values
+set before initialize is called will be left unchanged by
+initialization::
+
+ PyStatus init_python(const char *program_name)
+ {
+ PyStatus status;
+
+ PyConfig config;
+ PyConfig_InitPythonConfig(&config);
+
+ /* Set the program name before reading the configuration
+ (decode byte string from the locale encoding).
+
+ Implicitly preinitialize Python. */
+ status = PyConfig_SetBytesString(&config, &config.program_name,
+ program_name);
+ if (PyStatus_Exception(status)) {
+ goto done;
}
- // Initialize Python with the configuration
- if (Py_InitializeFromInitConfig(config) < 0) {
- goto error;
+ /* Read all configuration at once */
+ status = PyConfig_Read(&config);
+ if (PyStatus_Exception(status)) {
+ goto done;
}
- PyInitConfig_Free(config);
- return 0;
- error:
- {
- // Display the error message
- // This uncommon braces style is used, because you cannot make
- // goto targets point to variable declarations.
- const char *err_msg;
- (void)PyInitConfig_GetError(config, &err_msg);
- printf("PYTHON INIT ERROR: %s\n", err_msg);
- PyInitConfig_Free(config);
+ /* Specify sys.path explicitly */
+ /* If you want to modify the default set of paths, finish
+ initialization first and then use PySys_GetObject("path") */
+ config.module_search_paths_set = 1;
+ status = PyWideStringList_Append(&config.module_search_paths,
+ L"/path/to/stdlib");
+ if (PyStatus_Exception(status)) {
+ goto done;
+ }
+ status = PyWideStringList_Append(&config.module_search_paths,
+ L"/path/to/more/modules");
+ if (PyStatus_Exception(status)) {
+ goto done;
+ }
- return -1;
+ /* Override executable computed by PyConfig_Read() */
+ status = PyConfig_SetString(&config, &config.executable,
+ L"/path/to/my_executable");
+ if (PyStatus_Exception(status)) {
+ goto done;
}
+
+ status = Py_InitializeFromConfig(&config);
+
+ done:
+ PyConfig_Clear(&config);
+ return status;
}
-Runtime Python configuration API
-================================
+.. _init-isolated-conf:
-The configuration option *name* parameter must be a non-NULL null-terminated
-UTF-8 encoded string.
+Isolated Configuration
+----------------------
-Some options are read from the :mod:`sys` attributes. For example, the option
-``"argv"`` is read from :data:`sys.argv`.
+:c:func:`PyPreConfig_InitIsolatedConfig` and
+:c:func:`PyConfig_InitIsolatedConfig` functions create a configuration to
+isolate Python from the system. For example, to embed Python into an
+application.
+This configuration ignores global configuration variables, environment
+variables, command line arguments (:c:member:`PyConfig.argv` is not parsed)
+and user site directory. The C standard streams (ex: ``stdout``) and the
+LC_CTYPE locale are left unchanged. Signal handlers are not installed.
-.. c:function:: PyObject* PyConfig_Get(const char *name)
+Configuration files are still used with this configuration to determine
+paths that are unspecified. Ensure :c:member:`PyConfig.home` is specified
+to avoid computing the default path configuration.
- Get the current runtime value of a configuration option as a Python object.
- * Return a new reference on success.
- * Set an exception and return ``NULL`` on error.
+.. _init-python-config:
- The object type depends on the configuration option. It can be:
+Python Configuration
+--------------------
- * ``bool``
- * ``int``
- * ``str``
- * ``list[str]``
- * ``dict[str, str]``
+:c:func:`PyPreConfig_InitPythonConfig` and :c:func:`PyConfig_InitPythonConfig`
+functions create a configuration to build a customized Python which behaves as
+the regular Python.
- The caller must hold the GIL. The function cannot be called before
- Python initialization nor after Python finalization.
+Environments variables and command line arguments are used to configure
+Python, whereas global configuration variables are ignored.
- .. versionadded:: 3.14
+This function enables C locale coercion (:pep:`538`)
+and :ref:`Python UTF-8 Mode <utf8-mode>`
+(:pep:`540`) depending on the LC_CTYPE locale, :envvar:`PYTHONUTF8` and
+:envvar:`PYTHONCOERCECLOCALE` environment variables.
-.. c:function:: int PyConfig_GetInt(const char *name, int *value)
+.. _init-path-config:
- Similar to :c:func:`PyConfig_Get`, but get the value as a C int.
+Python Path Configuration
+-------------------------
- * Return ``0`` on success.
- * Set an exception and return ``-1`` on error.
+:c:type:`PyConfig` contains multiple fields for the path configuration:
- .. versionadded:: 3.14
+* Path configuration inputs:
+ * :c:member:`PyConfig.home`
+ * :c:member:`PyConfig.platlibdir`
+ * :c:member:`PyConfig.pathconfig_warnings`
+ * :c:member:`PyConfig.program_name`
+ * :c:member:`PyConfig.pythonpath_env`
+ * current working directory: to get absolute paths
+ * ``PATH`` environment variable to get the program full path
+ (from :c:member:`PyConfig.program_name`)
+ * ``__PYVENV_LAUNCHER__`` environment variable
+ * (Windows only) Application paths in the registry under
+ "Software\Python\PythonCore\X.Y\PythonPath" of HKEY_CURRENT_USER and
+ HKEY_LOCAL_MACHINE (where X.Y is the Python version).
-.. c:function:: PyObject* PyConfig_Names(void)
+* Path configuration output fields:
- Get all configuration option names as a ``frozenset``.
+ * :c:member:`PyConfig.base_exec_prefix`
+ * :c:member:`PyConfig.base_executable`
+ * :c:member:`PyConfig.base_prefix`
+ * :c:member:`PyConfig.exec_prefix`
+ * :c:member:`PyConfig.executable`
+ * :c:member:`PyConfig.module_search_paths_set`,
+ :c:member:`PyConfig.module_search_paths`
+ * :c:member:`PyConfig.prefix`
- * Return a new reference on success.
- * Set an exception and return ``NULL`` on error.
+If at least one "output field" is not set, Python calculates the path
+configuration to fill unset fields. If
+:c:member:`~PyConfig.module_search_paths_set` is equal to ``0``,
+:c:member:`~PyConfig.module_search_paths` is overridden and
+:c:member:`~PyConfig.module_search_paths_set` is set to ``1``.
- The caller must hold the GIL. The function cannot be called before
- Python initialization nor after Python finalization.
+It is possible to completely ignore the function calculating the default
+path configuration by setting explicitly all path configuration output
+fields listed above. A string is considered as set even if it is non-empty.
+``module_search_paths`` is considered as set if
+``module_search_paths_set`` is set to ``1``. In this case,
+``module_search_paths`` will be used without modification.
- .. versionadded:: 3.14
+Set :c:member:`~PyConfig.pathconfig_warnings` to ``0`` to suppress warnings when
+calculating the path configuration (Unix only, Windows does not log any warning).
+If :c:member:`~PyConfig.base_prefix` or :c:member:`~PyConfig.base_exec_prefix`
+fields are not set, they inherit their value from :c:member:`~PyConfig.prefix`
+and :c:member:`~PyConfig.exec_prefix` respectively.
-.. c:function:: int PyConfig_Set(const char *name, PyObject *value)
+:c:func:`Py_RunMain` and :c:func:`Py_Main` modify :data:`sys.path`:
- Set the current runtime value of a configuration option.
+* If :c:member:`~PyConfig.run_filename` is set and is a directory which contains a
+ ``__main__.py`` script, prepend :c:member:`~PyConfig.run_filename` to
+ :data:`sys.path`.
+* If :c:member:`~PyConfig.isolated` is zero:
- * Raise a :exc:`ValueError` if there is no option *name*.
- * Raise a :exc:`ValueError` if *value* is an invalid value.
- * Raise a :exc:`ValueError` if the option is read-only (cannot be set).
- * Raise a :exc:`TypeError` if *value* has not the proper type.
+ * If :c:member:`~PyConfig.run_module` is set, prepend the current directory
+ to :data:`sys.path`. Do nothing if the current directory cannot be read.
+ * If :c:member:`~PyConfig.run_filename` is set, prepend the directory of the
+ filename to :data:`sys.path`.
+ * Otherwise, prepend an empty string to :data:`sys.path`.
- The caller must hold the GIL. The function cannot be called before
- Python initialization nor after Python finalization.
+If :c:member:`~PyConfig.site_import` is non-zero, :data:`sys.path` can be
+modified by the :mod:`site` module. If
+:c:member:`~PyConfig.user_site_directory` is non-zero and the user's
+site-package directory exists, the :mod:`site` module appends the user's
+site-package directory to :data:`sys.path`.
- .. versionadded:: 3.14
+The following configuration files are used by the path configuration:
+
+* ``pyvenv.cfg``
+* ``._pth`` file (ex: ``python._pth``)
+* ``pybuilddir.txt`` (Unix only)
+
+If a ``._pth`` file is present:
+
+* Set :c:member:`~PyConfig.isolated` to ``1``.
+* Set :c:member:`~PyConfig.use_environment` to ``0``.
+* Set :c:member:`~PyConfig.site_import` to ``0``.
+* Set :c:member:`~PyConfig.safe_path` to ``1``.
+
+If :c:member:`~PyConfig.home` is not set and a ``pyvenv.cfg`` file is present in
+the same directory as :c:member:`~PyConfig.executable`, or its parent,
+:c:member:`~PyConfig.prefix` and :c:member:`~PyConfig.exec_prefix` are set that
+location. When this happens, :c:member:`~PyConfig.base_prefix` and
+:c:member:`~PyConfig.base_exec_prefix` still keep their value, pointing to the
+base installation. See :ref:`sys-path-init-virtual-environments` for more
+information.
+
+The ``__PYVENV_LAUNCHER__`` environment variable is used to set
+:c:member:`PyConfig.base_executable`.
+
+.. versionchanged:: 3.14
+
+ :c:member:`~PyConfig.prefix`, and :c:member:`~PyConfig.exec_prefix`, are now
+ set to the ``pyvenv.cfg`` directory. This was previously done by :mod:`site`,
+ therefore affected by :option:`-S`.
Py_GetArgcArgv()
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/0351ed50499c3d7fbefe126d025d32eb86…
commit: 0351ed50499c3d7fbefe126d025d32eb865ad3f0
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: Eclips4 <kirill.bast9(a)mail.ru>
date: 2025-01-20T10:37:21Z
summary:
[3.13] Fix a typo in `syslog`'s error message (GH-129029) (#129049)
Fix a typo in `syslog`'s error message (GH-129029)
(cherry picked from commit 9b1c1817af30e609b7cbfacbe5b1e73e21dc9e37)
Co-authored-by: Tomas R <tomas.roun8(a)gmail.com>
files:
M Modules/syslogmodule.c
diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c
index 14e7ca591a076b..adbd2fcc6ed74d 100644
--- a/Modules/syslogmodule.c
+++ b/Modules/syslogmodule.c
@@ -258,7 +258,7 @@ syslog_closelog_impl(PyObject *module)
// Since the sys.closelog changes the process level state of syslog library,
// this operation is only allowed for the main interpreter.
if (!is_main_interpreter()) {
- PyErr_SetString(PyExc_RuntimeError, "sunbinterpreter can't use syslog.closelog()");
+ PyErr_SetString(PyExc_RuntimeError, "subinterpreter can't use syslog.closelog()");
return NULL;
}
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/7f68e7bf2a768489ece13054d0cf9566d1…
commit: 7f68e7bf2a768489ece13054d0cf9566d176c576
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: Eclips4 <kirill.bast9(a)mail.ru>
date: 2025-01-20T10:28:55Z
summary:
[3.12] Fix a typo in `syslog`'s error message (GH-129029) (#129050)
Fix a typo in `syslog`'s error message (GH-129029)
(cherry picked from commit 9b1c1817af30e609b7cbfacbe5b1e73e21dc9e37)
Co-authored-by: Tomas R <tomas.roun8(a)gmail.com>
files:
M Modules/syslogmodule.c
diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c
index 6db8de9c491dd9..722364e0751d9f 100644
--- a/Modules/syslogmodule.c
+++ b/Modules/syslogmodule.c
@@ -250,7 +250,7 @@ syslog_closelog_impl(PyObject *module)
// Since the sys.closelog changes the process level state of syslog library,
// this operation is only allowed for the main interpreter.
if (!is_main_interpreter()) {
- PyErr_SetString(PyExc_RuntimeError, "sunbinterpreter can't use syslog.closelog()");
+ PyErr_SetString(PyExc_RuntimeError, "subinterpreter can't use syslog.closelog()");
return NULL;
}
1
0
https://github.com/python/cpython/commit/9b1c1817af30e609b7cbfacbe5b1e73e21…
commit: 9b1c1817af30e609b7cbfacbe5b1e73e21dc9e37
branch: main
author: Tomas R. <tomas.roun8(a)gmail.com>
committer: Eclips4 <kirill.bast9(a)mail.ru>
date: 2025-01-20T10:11:08Z
summary:
Fix a typo in `syslog`'s error message (#129029)
files:
M Modules/syslogmodule.c
diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c
index 14e7ca591a076b..adbd2fcc6ed74d 100644
--- a/Modules/syslogmodule.c
+++ b/Modules/syslogmodule.c
@@ -258,7 +258,7 @@ syslog_closelog_impl(PyObject *module)
// Since the sys.closelog changes the process level state of syslog library,
// this operation is only allowed for the main interpreter.
if (!is_main_interpreter()) {
- PyErr_SetString(PyExc_RuntimeError, "sunbinterpreter can't use syslog.closelog()");
+ PyErr_SetString(PyExc_RuntimeError, "subinterpreter can't use syslog.closelog()");
return NULL;
}
1
0
https://github.com/python/cpython/commit/07c3518ffb27875b14a0f1637aa85f773f…
commit: 07c3518ffb27875b14a0f1637aa85f773ff2f9ff
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-20T10:03:22Z
summary:
gh-129033: Remove _Py_InitializeMain() function (#129034)
Co-authored-by: Alyssa Coghlan <ncoghlan(a)gmail.com>
files:
A Misc/NEWS.d/next/C_API/2025-01-19-23-17-58.gh-issue-129033.cpRivP.rst
M Doc/c-api/init_config.rst
M Doc/whatsnew/3.14.rst
M Include/cpython/pylifecycle.h
M Lib/test/test_embed.py
M Programs/_testembed.c
M Python/pylifecycle.c
diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst
index 6b33d93a9f2af9..85566631ca1676 100644
--- a/Doc/c-api/init_config.rst
+++ b/Doc/c-api/init_config.rst
@@ -1946,89 +1946,13 @@ Py_GetArgcArgv()
See also :c:member:`PyConfig.orig_argv` member.
+Delaying main module execution
+==============================
-Multi-Phase Initialization Private Provisional API
-==================================================
+In some embedding use cases, it may be desirable to separate interpreter initialization
+from the execution of the main module.
-This section is a private provisional API introducing multi-phase
-initialization, the core feature of :pep:`432`:
-
-* "Core" initialization phase, "bare minimum Python":
-
- * Builtin types;
- * Builtin exceptions;
- * Builtin and frozen modules;
- * The :mod:`sys` module is only partially initialized
- (ex: :data:`sys.path` doesn't exist yet).
-
-* "Main" initialization phase, Python is fully initialized:
-
- * Install and configure :mod:`importlib`;
- * Apply the :ref:`Path Configuration <init-path-config>`;
- * Install signal handlers;
- * Finish :mod:`sys` module initialization (ex: create :data:`sys.stdout`
- and :data:`sys.path`);
- * Enable optional features like :mod:`faulthandler` and :mod:`tracemalloc`;
- * Import the :mod:`site` module;
- * etc.
-
-Private provisional API:
-
-* :c:member:`PyConfig._init_main`: if set to ``0``,
- :c:func:`Py_InitializeFromConfig` stops at the "Core" initialization phase.
-
-.. c:function:: PyStatus _Py_InitializeMain(void)
-
- Move to the "Main" initialization phase, finish the Python initialization.
-
-No module is imported during the "Core" phase and the ``importlib`` module is
-not configured: the :ref:`Path Configuration <init-path-config>` is only
-applied during the "Main" phase. It may allow to customize Python in Python to
-override or tune the :ref:`Path Configuration <init-path-config>`, maybe
-install a custom :data:`sys.meta_path` importer or an import hook, etc.
-
-It may become possible to calculate the :ref:`Path Configuration
-<init-path-config>` in Python, after the Core phase and before the Main phase,
-which is one of the :pep:`432` motivation.
-
-The "Core" phase is not properly defined: what should be and what should
-not be available at this phase is not specified yet. The API is marked
-as private and provisional: the API can be modified or even be removed
-anytime until a proper public API is designed.
-
-Example running Python code between "Core" and "Main" initialization
-phases::
-
- void init_python(void)
- {
- PyStatus status;
-
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
- config._init_main = 0;
-
- /* ... customize 'config' configuration ... */
-
- status = Py_InitializeFromConfig(&config);
- PyConfig_Clear(&config);
- if (PyStatus_Exception(status)) {
- Py_ExitStatusException(status);
- }
-
- /* Use sys.stderr because sys.stdout is only created
- by _Py_InitializeMain() */
- int res = PyRun_SimpleString(
- "import sys; "
- "print('Run Python code before _Py_InitializeMain', "
- "file=sys.stderr)");
- if (res < 0) {
- exit(1);
- }
-
- /* ... put more configuration code here ... */
-
- status = _Py_InitializeMain();
- if (PyStatus_Exception(status)) {
- Py_ExitStatusException(status);
- }
- }
+This separation can be achieved by setting ``PyConfig.run_command`` to the empty
+string during initialization (to prevent the interpreter from dropping into the
+interactive prompt), and then subsequently executing the desired main module
+code using ``__main__.__dict__`` as the global namespace.
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index d6aa6b346417e5..7f149d5c03dfbb 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -1375,3 +1375,7 @@ Removed
* Creating :c:data:`immutable types <Py_TPFLAGS_IMMUTABLETYPE>` with mutable
bases was deprecated since 3.12 and now raises a :exc:`TypeError`.
+
+* Remove the private ``_Py_InitializeMain()`` function. It was a
+ :term:`provisional API` added to Python 3.8 by :pep:`587`.
+ (Contributed by Victor Stinner in :gh:`129033`.)
diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h
index e46dfe59ec4630..86ce6e6f79824a 100644
--- a/Include/cpython/pylifecycle.h
+++ b/Include/cpython/pylifecycle.h
@@ -25,9 +25,6 @@ PyAPI_FUNC(PyStatus) Py_PreInitializeFromArgs(
PyAPI_FUNC(PyStatus) Py_InitializeFromConfig(
const PyConfig *config);
-// Python 3.8 provisional API (PEP 587)
-PyAPI_FUNC(PyStatus) _Py_InitializeMain(void);
-
PyAPI_FUNC(int) Py_RunMain(void);
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index 1b55cd156d759d..a2400aa96c3ddd 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -1274,24 +1274,6 @@ def test_init_run_main(self):
}
self.check_all_configs("test_init_run_main", config, api=API_PYTHON)
- def test_init_main(self):
- code = ('import _testinternalcapi, json; '
- 'print(json.dumps(_testinternalcapi.get_configs()))')
- config = {
- 'argv': ['-c', 'arg2'],
- 'orig_argv': ['python3',
- '-c', code,
- 'arg2'],
- 'program_name': './python3',
- 'run_command': code + '\n',
- 'parse_argv': True,
- '_init_main': False,
- 'sys_path_0': '',
- }
- self.check_all_configs("test_init_main", config,
- api=API_PYTHON,
- stderr="Run Python code before _Py_InitializeMain")
-
def test_init_parse_argv(self):
config = {
'parse_argv': True,
@@ -1768,7 +1750,6 @@ def test_init_warnoptions(self):
def test_init_set_config(self):
config = {
- '_init_main': 0,
'bytes_warning': 2,
'warnoptions': ['error::BytesWarning'],
}
diff --git a/Misc/NEWS.d/next/C_API/2025-01-19-23-17-58.gh-issue-129033.cpRivP.rst b/Misc/NEWS.d/next/C_API/2025-01-19-23-17-58.gh-issue-129033.cpRivP.rst
new file mode 100644
index 00000000000000..3cd19cc48e3416
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2025-01-19-23-17-58.gh-issue-129033.cpRivP.rst
@@ -0,0 +1,3 @@
+Remove the private ``_Py_InitializeMain()`` function. It was a
+:term:`provisional API` added to Python 3.8 by :pep:`587`. Patch by Victor
+Stinner.
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
index d15dd519dbf6af..3681a89376638a 100644
--- a/Programs/_testembed.c
+++ b/Programs/_testembed.c
@@ -1818,7 +1818,6 @@ static int test_init_set_config(void)
PyConfig config;
PyConfig_InitIsolatedConfig(&config);
config_set_string(&config, &config.program_name, PROGRAM_NAME);
- config._init_main = 0;
config.bytes_warning = 0;
init_from_config_clear(&config);
@@ -1828,12 +1827,6 @@ static int test_init_set_config(void)
return 1;
}
- // Finish initialization: main part
- PyStatus status = _Py_InitializeMain();
- if (PyStatus_Exception(status)) {
- Py_ExitStatusException(status);
- }
-
dump_config();
Py_Finalize();
return 0;
@@ -2089,33 +2082,6 @@ static int test_init_run_main(void)
}
-static int test_init_main(void)
-{
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
-
- configure_init_main(&config);
- config._init_main = 0;
- init_from_config_clear(&config);
-
- /* sys.stdout don't exist yet: it is created by _Py_InitializeMain() */
- int res = PyRun_SimpleString(
- "import sys; "
- "print('Run Python code before _Py_InitializeMain', "
- "file=sys.stderr)");
- if (res < 0) {
- exit(1);
- }
-
- PyStatus status = _Py_InitializeMain();
- if (PyStatus_Exception(status)) {
- Py_ExitStatusException(status);
- }
-
- return Py_RunMain();
-}
-
-
static int test_run_main(void)
{
PyConfig config;
@@ -2473,7 +2439,6 @@ static struct TestCase TestCases[] = {
{"test_preinit_dont_parse_argv", test_preinit_dont_parse_argv},
{"test_init_read_set", test_init_read_set},
{"test_init_run_main", test_init_run_main},
- {"test_init_main", test_init_main},
{"test_init_sys_add", test_init_sys_add},
{"test_init_setpath", test_init_setpath},
{"test_init_setpath_config", test_init_setpath_config},
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index f1ecee6a92e5a1..8ec12b437f8298 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -1505,18 +1505,6 @@ Py_Initialize(void)
}
-PyStatus
-_Py_InitializeMain(void)
-{
- PyStatus status = _PyRuntime_Initialize();
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
- PyThreadState *tstate = _PyThreadState_GET();
- return pyinit_main(tstate);
-}
-
-
static void
finalize_modules_delete_special(PyThreadState *tstate, int verbose)
{
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/c463270c73a61ef8106ee7bd0571c7c614…
commit: c463270c73a61ef8106ee7bd0571c7c6143e2c20
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2025-01-20T11:22:33+02:00
summary:
gh-71339: Use new assertion methods in test_traceback (GH-128848)
files:
M Lib/test/test_traceback.py
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py
index abdfc4638f2e9c..a27a71c32ea521 100644
--- a/Lib/test/test_traceback.py
+++ b/Lib/test/test_traceback.py
@@ -86,7 +86,7 @@ def test_caret(self):
err = self.get_exception_format(self.syntax_error_with_caret,
SyntaxError)
self.assertEqual(len(err), 4)
- self.assertTrue(err[1].strip() == "return x!")
+ self.assertEqual(err[1].strip(), "return x!")
self.assertIn("^", err[2]) # third line has caret
self.assertEqual(err[1].find("!"), err[2].find("^")) # in the right place
self.assertEqual(err[2].count("^"), 1)
@@ -419,16 +419,10 @@ def do_test(firstlines, message, charset, lineno):
err_line = "raise RuntimeError('{0}')".format(message_ascii)
err_msg = "RuntimeError: {0}".format(message_ascii)
- self.assertIn(("line %s" % lineno), stdout[1],
- "Invalid line number: {0!r} instead of {1}".format(
- stdout[1], lineno))
- self.assertTrue(stdout[2].endswith(err_line),
- "Invalid traceback line: {0!r} instead of {1!r}".format(
- stdout[2], err_line))
+ self.assertIn("line %s" % lineno, stdout[1])
+ self.assertEndsWith(stdout[2], err_line)
actual_err_msg = stdout[3]
- self.assertTrue(actual_err_msg == err_msg,
- "Invalid error message: {0!r} instead of {1!r}".format(
- actual_err_msg, err_msg))
+ self.assertEqual(actual_err_msg, err_msg)
do_test("", "foo", "ascii", 3)
for charset in ("ascii", "iso-8859-1", "utf-8", "GBK"):
@@ -1809,9 +1803,9 @@ def check_traceback_format(self, cleanup_func=None):
banner = tb_lines[0]
self.assertEqual(len(tb_lines), 5)
location, source_line = tb_lines[-2], tb_lines[-1]
- self.assertTrue(banner.startswith('Traceback'))
- self.assertTrue(location.startswith(' File'))
- self.assertTrue(source_line.startswith(' raise'))
+ self.assertStartsWith(banner, 'Traceback')
+ self.assertStartsWith(location, ' File')
+ self.assertStartsWith(source_line, ' raise')
def test_traceback_format(self):
self.check_traceback_format()
@@ -2190,12 +2184,12 @@ def zero_div(self):
def check_zero_div(self, msg):
lines = msg.splitlines()
if has_no_debug_ranges():
- self.assertTrue(lines[-3].startswith(' File'))
+ self.assertStartsWith(lines[-3], ' File')
self.assertIn('1/0 # In zero_div', lines[-2])
else:
- self.assertTrue(lines[-4].startswith(' File'))
+ self.assertStartsWith(lines[-4], ' File')
self.assertIn('1/0 # In zero_div', lines[-3])
- self.assertTrue(lines[-1].startswith('ZeroDivisionError'), lines[-1])
+ self.assertStartsWith(lines[-1], 'ZeroDivisionError')
def test_simple(self):
try:
@@ -2205,12 +2199,12 @@ def test_simple(self):
lines = self.get_report(e).splitlines()
if has_no_debug_ranges():
self.assertEqual(len(lines), 4)
- self.assertTrue(lines[3].startswith('ZeroDivisionError'))
+ self.assertStartsWith(lines[3], 'ZeroDivisionError')
else:
self.assertEqual(len(lines), 5)
- self.assertTrue(lines[4].startswith('ZeroDivisionError'))
- self.assertTrue(lines[0].startswith('Traceback'))
- self.assertTrue(lines[1].startswith(' File'))
+ self.assertStartsWith(lines[4], 'ZeroDivisionError')
+ self.assertStartsWith(lines[0], 'Traceback')
+ self.assertStartsWith(lines[1], ' File')
self.assertIn('1/0 # Marker', lines[2])
def test_cause(self):
@@ -2251,9 +2245,9 @@ def test_context_suppression(self):
e = _
lines = self.get_report(e).splitlines()
self.assertEqual(len(lines), 4)
- self.assertTrue(lines[3].startswith('ZeroDivisionError'))
- self.assertTrue(lines[0].startswith('Traceback'))
- self.assertTrue(lines[1].startswith(' File'))
+ self.assertStartsWith(lines[3], 'ZeroDivisionError')
+ self.assertStartsWith(lines[0], 'Traceback')
+ self.assertStartsWith(lines[1], ' File')
self.assertIn('ZeroDivisionError from None', lines[2])
def test_cause_and_context(self):
1
0
gh-71339: Use assertIsSubclass() and assertNotIsSubclass() in test_decimal (GH-128827)
by serhiy-storchaka Jan. 20, 2025
by serhiy-storchaka Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/485d2e831ebf71a34634319adeeabdd1f9…
commit: 485d2e831ebf71a34634319adeeabdd1f9158bbe
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2025-01-20T11:20:49+02:00
summary:
gh-71339: Use assertIsSubclass() and assertNotIsSubclass() in test_decimal (GH-128827)
files:
M Lib/test/test_decimal.py
diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
index bc6c6427740949..02d3fa985e75b9 100644
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -752,7 +752,7 @@ def test_explicit_context_create_decimal(self):
for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
2**31-1, 2**31, 2**63-1, 2**63]:
d = nc.create_decimal(v)
- self.assertTrue(isinstance(d, Decimal))
+ self.assertIsInstance(d, Decimal)
self.assertEqual(int(d), v)
nc.prec = 3
@@ -2590,8 +2590,8 @@ class PythonAPItests:
def test_abc(self):
Decimal = self.decimal.Decimal
- self.assertTrue(issubclass(Decimal, numbers.Number))
- self.assertFalse(issubclass(Decimal, numbers.Real))
+ self.assertIsSubclass(Decimal, numbers.Number)
+ self.assertNotIsSubclass(Decimal, numbers.Real)
self.assertIsInstance(Decimal(0), numbers.Number)
self.assertNotIsInstance(Decimal(0), numbers.Real)
@@ -2690,7 +2690,7 @@ class MyDecimal(Decimal):
def __init__(self, _):
self.x = 'y'
- self.assertTrue(issubclass(MyDecimal, Decimal))
+ self.assertIsSubclass(MyDecimal, Decimal)
r = MyDecimal.from_float(0.1)
self.assertEqual(type(r), MyDecimal)
@@ -2908,31 +2908,31 @@ def test_exception_hierarchy(self):
Rounded = decimal.Rounded
Clamped = decimal.Clamped
- self.assertTrue(issubclass(DecimalException, ArithmeticError))
-
- self.assertTrue(issubclass(InvalidOperation, DecimalException))
- self.assertTrue(issubclass(FloatOperation, DecimalException))
- self.assertTrue(issubclass(FloatOperation, TypeError))
- self.assertTrue(issubclass(DivisionByZero, DecimalException))
- self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
- self.assertTrue(issubclass(Overflow, Rounded))
- self.assertTrue(issubclass(Overflow, Inexact))
- self.assertTrue(issubclass(Overflow, DecimalException))
- self.assertTrue(issubclass(Underflow, Inexact))
- self.assertTrue(issubclass(Underflow, Rounded))
- self.assertTrue(issubclass(Underflow, Subnormal))
- self.assertTrue(issubclass(Underflow, DecimalException))
-
- self.assertTrue(issubclass(Subnormal, DecimalException))
- self.assertTrue(issubclass(Inexact, DecimalException))
- self.assertTrue(issubclass(Rounded, DecimalException))
- self.assertTrue(issubclass(Clamped, DecimalException))
-
- self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
- self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
- self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
- self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
- self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
+ self.assertIsSubclass(DecimalException, ArithmeticError)
+
+ self.assertIsSubclass(InvalidOperation, DecimalException)
+ self.assertIsSubclass(FloatOperation, DecimalException)
+ self.assertIsSubclass(FloatOperation, TypeError)
+ self.assertIsSubclass(DivisionByZero, DecimalException)
+ self.assertIsSubclass(DivisionByZero, ZeroDivisionError)
+ self.assertIsSubclass(Overflow, Rounded)
+ self.assertIsSubclass(Overflow, Inexact)
+ self.assertIsSubclass(Overflow, DecimalException)
+ self.assertIsSubclass(Underflow, Inexact)
+ self.assertIsSubclass(Underflow, Rounded)
+ self.assertIsSubclass(Underflow, Subnormal)
+ self.assertIsSubclass(Underflow, DecimalException)
+
+ self.assertIsSubclass(Subnormal, DecimalException)
+ self.assertIsSubclass(Inexact, DecimalException)
+ self.assertIsSubclass(Rounded, DecimalException)
+ self.assertIsSubclass(Clamped, DecimalException)
+
+ self.assertIsSubclass(decimal.ConversionSyntax, InvalidOperation)
+ self.assertIsSubclass(decimal.DivisionImpossible, InvalidOperation)
+ self.assertIsSubclass(decimal.DivisionUndefined, InvalidOperation)
+ self.assertIsSubclass(decimal.DivisionUndefined, ZeroDivisionError)
+ self.assertIsSubclass(decimal.InvalidContext, InvalidOperation)
@requires_cdecimal
class CPythonAPItests(PythonAPItests, unittest.TestCase):
1
0