-
-
Notifications
You must be signed in to change notification settings - Fork 31.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The global config should not be stored on each interpreter #91120
Comments
tl;dr let's move PyInterpreterState.config to _PyRuntimeState.config. Historically the runtime has been initialized using Py_Initialize(). PEP-587 added Py_InitializeFromConfig(), which takes a PyConfig and allows all sorts of customization of the runtime. This is valuable for embedders (and benefits core development too). During runtime initialization the given config is copied and stored internally on the main interpreter. Once initialization completes, the config is no longer modified. The config values are then used in a variety of places during execution. If a new interpreter is created then the config from the current (or main) interpreter are copied into it. Note the following:
Consequently, PyConfig really is the global runtime config. Yet we are storing a copy of it on each interpreter. Doing so unnecessarily adds extra complexity (and, when multiple interpreters are used, extra CPU usage and extra memory usage). So I propose that we move the config to _PyRuntimeState. The change isn't big nor all that complex. Note that actually there is one field that can differ between interpreters: PyConfig._isolated_interpreter (set in _Py_NewInterpreter()). We can move that one field to a new per-interpreter config struct. |
Right, PyConfig allocates memory per interpeter. But IMO it's an acceptable trade-off. I don't see the benefits of sharing the config between all interpreters. Have per-interpreter config allows to create an interpreter with a different config:
While there is currently no easy way to use a custom config, recent changes make it easier to implement, like the function to modify a PyConfig from a Python dict: _PyInterpreterState_SetConfig().
Barry Warsaw proposed to add a function to get the config, but I didn't add it. There are private functions for that:
|
Here are reasons why PyConfig relates to the runtime and not each interpreter:
This is why PyConfig makes more sense as the global config, not a per-interpreter one. I think it was a mistake to store the config on PyInterpreterState. Keep in mind, though, that PyConfig was added several years before _PyRuntimeState existed. If _PyRuntimeState had been around, I'm sure that's where we would have kept the global config. Thus, it makes sense to move PyInterpreterState.config to _PyRuntimeState.config. If there's a need for a per-interpreter config later, we would do the following:
In fact, that is exactly what I'm proposing in PEP-684, where there is a need for creating an interpreter with various isolation options. That's what got me thinking about why PyConfig isn't good for customizing new interpreters. Even if we didn't move PyInterpreterState.config to _PyRuntimeState.config, PEP-684 would still not use PyConfig as the config to pass when creating a new interpreter. Using PyConfig would be confusing and an invitation for trouble. So I'd use a new PyInterpreterConfig either way. Consequently, having PyConfig on PyInterpreterState would be confusing, with no benefit. My intention with this BPO issue was to get our internal details aligned with what makes sense for a global config and set the stage for adding a proper per-interpreter config. |
I don't think that sub-interpreters should have config.install_signal_handlers=1. Same for config.configure_c_stdio=1. Only the main interpreter should handle signals and the configuration of C streams (stdio, stderr, stdio). I added _PyInterpreterState_SetConfig() to experiment changing config.bytes_warning. But this is no strong need to have an API to change it, so right now, there is still no API for that. If we allow to change it, it would be surprising to change all interpreters at once. I don't see why config.argv (sys.argv) must be the same in all interpreters. Same for config.module_search_paths (sys.path). For me, it makes sense to have a per-interpreter value for most PyConfig options.
There is _Py_NewInterpreter(int isolated_subinterpreter) to set config.config._isolated_interpreter. But since the feature is not "official", it remains a private API.
Currently, it's possible to call Py_InitializeFromConfig() (or Py_Initialize()) multiple times and it changes the PyConfig of the current interpreter. See the pyinit_core_reconfigure() function. _testembed has an unit test for that: I had to implement this feature. Once, calling the function multiple times and it broke an application. See bpo-34008. |
Moving the invariant bits would certainly make sense. As Victor notes, though, some things (like whether to install the signal handlers) should be different. |
IMO it's convenient to have a single structure for all "configuration", even if a few parameters are expected to be the same in all interpreters. Python/initconfig.c is already a long C file. It contains a lot of code to copy members, converts them from a dict/to a dict, check consistency, etc. It's also a little bit annoying (for me) to have a separated PyPreConfig structure int Python/preconfig.c which shares some code (like the "_PyPreCmdline" thing to parse "common" command line options). Well, that's the opinon of the author of PEP-587, biaised obviously ;-) |
I agree the status quo has its benefits. However, it has the distinct downside that because each interpreter has its own storage for copied settings, other code has to assume the settings *might* be different in each interpreter, even if they're currently always the same. If the invariant bits are moved out, then it clearly indicates when code can safely assume that every interpreter will be seeing the same value. |
What is the benefit of that? Do you have an example? |
Minor update. PEP 741 added |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: