I think making the configuration structure opaque and using an API to set/get configuration by name is a welcome simplification:
- it’s a smaller API for language bindings like PyO3 to wrap and re-expose, and
- it’s easier for people to support multiple Python versions to embed into their application; no need to conditionally compile structure field access, can just use normal error handling if configuration values are not available for a specific version at runtime.
I’m going to stay away from the question of whether users should be vendoring their own copy of Python or distributing apps which are expected to work with a system Python etc. On the PyO3 issue tracker I’ve had users wanting to do both of these things, for their own reasons. I think the bullets above apply regardless of distribution option.
Effect on the Stable ABI
It seems to me that there are two main new concepts which this PEP would add to the stable ABI:
-
The two steps “preinitialize” and “initialize”, and I wish it didn’t (I’ll cover that more below).
-
Programmatic control of the configuration variables. This would be helpful, as using the stable ABI’s
Py_InitializeEx
already allows for a lot of configuration to be read as environment variables. Being able to use the “isolated config” from PEP 587, for example, would be great; at the moment setting a badPYTHONHOME
value can probably break most Rust applications built with a Python embedded via PyO3.
Preinitialization 
I like how this API merges PyConfig
and PyPreConfig
of PEP 587 into an opaque structure.
Py_PreInitializeFromInitConfig
is missing from the “Specification” bullet list even though it is described down in the full documentation. That got me briefly excited, I think that having multiple steps to initialize from the one configuration object is more complex than it might need to be.
-
Is it an error to modify the
PyInitConfig
after preinitialization? -
Could we have APIs like
PyInitConfig_AddInittab
orPyInitConfig_AddInittabHook
, which are used to control the few operations legal between preinitialization and full intialization? -
Is there anything besides editing the inittab which is expected to be done between the two phases of initialization?
I would love it if it’s possible to adjust the PEP to remove the preinitialization step and add some extra configuration for the inittab (and any other similar bits which would be needed).
I think then this would be a straightforward replacement for Py_InitializeEx
where the embedding user gets more control to set the configuration they care about.
Alternative Runtimes
This API might also be very interesting to alternative Python runtimes like PyPy and GraalPy. I suspect that supporting PEP 587 would be difficult due to those runtimes likely needing very different configuration variables, but this API might be possible.
(and a bikeshed, sorry…)
As a final bikeshed, it was a bit surprising to me that a structure called PyInitConfig
contains error state. I don’t readily have a better name though, PyInitializer
maybe?