Include/internal/pycore_initconfig.h
cpython 3.14 @ ab2d84fe1023/Include/internal/pycore_initconfig.h
This is one of the largest internal headers in CPython. It defines every struct and function involved in interpreter startup configuration. The public story (PEP 587, shipped in 3.8) exposes PyConfig and PyPreConfig to embedders; this header adds the private fields, the intermediate _PyPreConfig and _PyCoreConfig structs used during the multi-phase init sequence, the _PyArgv wrapper for argc/argv, and the full set of _PyConfig_Read / _PyConfig_Write helpers. Understanding this file is a prerequisite for understanding how any of Py_InitializeFromConfig, Py_RunMain, or subinterpreter creation works.
Map
| Lines | Symbol | Role | gopy |
|---|---|---|---|
| ~20-40 | _PyArgv | Wraps (argc, wchar_t** wargv) or (argc, char** argv) | not ported |
| ~45-90 | _PyPreConfig | Pre-init config: locale, allocator, UTF-8 mode | not ported |
| ~95-280 | PyConfig | Full public config struct (PEP 587) | partial (see runtime init) |
| ~285-310 | _PyCoreConfig | Internal-only fields not exposed in PyConfig | not ported |
| ~315-330 | PyConfig_Read | Parse env vars, cmdline, and defaults into PyConfig | not ported |
| ~335-360 | _PyConfig_InitPathConfig | Compute sys.path, prefix, exec_prefix | not ported |
| ~365-380 | _Py_GetConfigsAsDict | Serialize all three config structs to a dict | not ported |
Reading
_PyArgv and pre-init phase (lines ~20 to 90)
The initialization pipeline runs in two phases. Phase 1 (pre-init) must run before the allocator is finalized and before any Python objects can be created. _PyArgv carries the raw command-line arguments through this phase without allocating Python objects:
typedef struct {
Py_ssize_t argc;
int use_bytes_argv;
char * const *bytes_argv;
const wchar_t * const *wchar_argv;
} _PyArgv;
_PyPreConfig is populated during phase 1 from _PyArgv plus environment variables. Its fields control the memory allocator selection (PYTHONMALLOC), locale coercion (PYTHONCOERCECLOCALE), and UTF-8 mode (PYTHONUTF8). All three of these must be known before Py_Initialize can safely call PyMem_Malloc or convert the argv bytes to wide characters.
PyConfig fields (lines ~95 to 280)
PyConfig is the largest struct in this header. Selected fields of note:
typedef struct PyConfig {
int _config_init; /* _PyConfigInitEnum */
int isolated;
int use_environment;
int dev_mode;
int install_signal_handlers;
int use_hash_randomization;
int faulthandler;
int tracemalloc;
int perf_profiling;
int import_time;
int code_debug_ranges;
int show_ref_count;
int dump_refs;
wchar_t *dump_refs_file;
int malloc_stats;
wchar_t *filesystem_encoding;
wchar_t *filesystem_errors;
wchar_t *pycache_prefix;
int parse_argv;
PyWideStringList orig_argv;
PyWideStringList argv;
PyWideStringList xoptions;
PyWideStringList warnoptions;
int site_import;
int bytes_warning;
int warn_default_encoding;
int inspect;
int interactive;
int optimization_level;
int parser_debug;
int write_bytecode;
int verbose;
int quiet;
int user_site_directory;
int configure_c_stdio;
int buffered_stdio;
wchar_t *stdio_encoding;
wchar_t *stdio_errors;
wchar_t *check_hash_based_pycs;
int pathconfig_warnings;
wchar_t *program_name;
wchar_t *pythonpath_env;
wchar_t *home;
wchar_t *platlibdir;
PyWideStringList sys_path_0;
int module_search_paths_set;
PyWideStringList module_search_paths;
wchar_t *stdlib_dir;
wchar_t *executable;
wchar_t *base_executable;
wchar_t *prefix;
wchar_t *base_prefix;
wchar_t *exec_prefix;
wchar_t *base_exec_prefix;
int skip_source_first_line;
wchar_t *run_command;
wchar_t *run_module;
wchar_t *run_filename;
int _install_importlib;
int _init_main;
int _is_python_build;
} PyConfig;
The _config_init sentinel distinguishes between a struct zero-initialized by PyConfig_InitPythonConfig and one that the embedder partially filled in. PyConfig_Read checks this flag and skips re-reading fields that the embedder already set.
PyConfig_Read and the read pipeline (lines ~315 to 360)
PyConfig_Read is the main entry point that embedders call after filling in the fields they care about:
PyStatus PyConfig_Read(PyConfig *config);
Internally it calls a chain of helpers in order:
_PyConfig_Read_PYTHONPATH- readsPYTHONPATHfrom the environment._PyConfig_InitPathConfig- invokes the platform-specificpathconfigcode to setprefix,exec_prefix,stdlib_dir, andmodule_search_paths._PyConfig_Read_WarningOptions- merges-Wflags,PYTHONWARNINGS, andsys.warnoptions._PyConfig_Read_XOptions- merges-Xflags intoxoptions.
The function returns a PyStatus value. PyStatus_Exception is true whenever an error occurred; the caller must check this before proceeding to Py_InitializeFromConfig. Errors at this stage cannot raise Python exceptions because no interpreter exists yet, so they are signalled as C-level status structs with an embedded error message string.
gopy mirror
gopy handles basic interpreter configuration in the runtime initialization code rather than through a port of PyConfig. There is no _PyPreConfig equivalent and no two-phase init. The module/sys/module.go implementation sets a small number of sys attributes (sys.argv, sys.path, sys.version, sys.platform) directly from Go variables at startup. Fields like optimization_level, write_bytecode, verbose, and quiet have no gopy counterpart yet. A full port of PyConfig would likely map to a Go struct passed into a runtime.Initialize(cfg Config) call, mirroring the PEP 587 embedder API.
CPython 3.14 changes
3.14 adds perf_profiling to PyConfig (controlling sys.monitoring-based perf map output) and code_debug_ranges (controlling the extended line-table entries written into .pyc files for the new per-instruction source ranges). dump_refs_file is new: in earlier versions dump_refs always wrote to stderr; 3.14 lets embedders redirect the output to a named file. sys_path_0 is a new field that controls what gets prepended to sys.path instead of the old implicit logic that depended on run_module / run_filename / run_command being set.