| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
Add init_callback and init_callback_arg members to PyConfig.
|
Current documentation:
|
Sorry, something went wrong.
|
@indygreg: Hi, would such C API fit your needs for PyOxidizer? |
Sorry, something went wrong.
Sorry, something went wrong.
That is extremely vague. If there are no concrete promises about what's available, and what APIs can be called, new versions of CPython are theoretically allowed to "break" callers. Is the callback better than restoring older private "multi-phase" API? Would it be better to add API specifically for adding a simple metapath entry? |
Sorry, something went wrong.
It's vague on purpose, but you're right that it should be better specified. Python 3.13 documentation specify what is available at the "core" phase and what is the "main" phase: https://docs.python.org/3.13/c-api/init_config.html#multi-phase-initialization-private-provisional-api
Good question. I just tested: you can import built-in modules at this point, but only built-in modules. importlib is not fully initialized yet.
The old API (Python 3.13 and older) allows not executing the "main" initialization phase, but IMO it makes no sense (there is not use case for that). What's needed is only to inject code (callback) between the "core" and the "main" initialization phase. IMO a callback API better fits the use case.
I'm not aware of other points which would be interesting during the initialization.
The bypy code to inject the sys.meta_path hook is non-trivial: The PyOxidizer code is also complex: |
Sorry, something went wrong.
I completed the documentation using Python 3.13 doc. |
Sorry, something went wrong.
That's worrying: it means that if we rewrite a module in Python, we break people's code. (For example, the bypy hook depends on marshal being built-in. In this case I guess they could switch to PyMarshal_ReadObjectFromString, but, that's still a code change...)
What's worrying for metapath entries is that "importlib", "Path Configuration" and "sys.path initialization" come after the hook call. It sounds like any change in this are could break users of the hook. This does look like it should be unstable at least. But, I believe it would be best to bring the old private API back (deprecated) while a better alternative is designed: |
Sorry, something went wrong.
Sorry, something went wrong.
These things changed multiple times since PEP 587 (PyConfig C API) has been implemented, and it was just fine with users of the "Multi-Phase Initialization Private Provisional API". For example, the path configuration has been reimplemented in Python in Python 3.11 (Modules/getpath.py).
Well, a provisional API has a different backward compatibility contract: https://docs.python.org/dev/glossary.html#term-provisional-API
Anyway, the API has already been removed from Python 3.14. |
Sorry, something went wrong.
It also says:
What are the serious fundamental flaws that were missed? |
Sorry, something went wrong.
and
These issues already existed in Python 3.13 with the provisional _init_main=0 / _Py_InitializeMain() API. Proposed PyInitConfig_SetInitCallback() has the same issues than adding back _Py_InitializeMain() to Python 3.15. As I wrote previously, it's not an issue in practice, and this code already changed multiple times without breaking projects using _Py_InitializeMain().
I removed the _Py_InitializeMain() API because I failed to find any user of this provisional/private API. But there are at least two users in the wild (bypy and PyOxidizer), so I would prefer to add a documented and tested public API to replace it.
Python 3.13 API allows to not execute the "main" initialization phase. This is not needed by 3rd party projects and I would like to avoid that. PyInitConfig_SetInitCallback() ensures that Python is always initialized the same way (always execute the "main" initialization phase). |
Sorry, something went wrong.
Right.
Is that the only benefit?
Where did you look? |
Sorry, something went wrong.
|
I propose replacing _Py_InitializeMain() with PyInitConfig_SetInitCallback() because I don't want to expose the concepts of "core initialization" and "main initialization" in the API. A callback is easier to document and explain.
I don't recall, but I likely looked in PyPI top 15,000 projects. |
Sorry, something went wrong.
Fair. I don't think that qualifies as a serious fundamental flaw though.
Yeah. The extension module index isn't a good place for users of runtime initialization API. |
Sorry, something went wrong.
I think we should, though not necessarily under these names. There's no reasons why embedders shouldn't be able to "initialize up to pre-importlib", do stuff, and then "initialize importlib and anything after it". That's more or less what we currently do, where the "do stuff" is running getpath.py. It would also help our own tools, where we need to half-initialize the runtime in order to freeze modules during build, etc. It might not directly fix the problem being looked at here, but it's the design we've been aiming towards for a decade now, so it ought to be the goal. If that means bringing back the API that was removed in the meantime, that seems fine. The only thing we gain by rushing initialisation API changes is cruft, so we're better off keeping the cruft we already have and getting the API design right. |
Sorry, something went wrong.
|
Oh, I'll also point out that I think it makes perfect structural sense for getpath.py to belong to python.exe rather than libpython.so, which would imply that it's possible to do the three steps using only the public API. For practical reasons, we wouldn't make that a real move, but structurally I think it helps to visualise importlib as part of "Python the command-line tool" rather than "Python the embeddable library" (since when embedding, you often want a different kind of importer than importlib's defaults). |
Sorry, something went wrong.
Unfortunately, I think that would break a number of use-cases, but we could definitely move the C API towards that. |
Sorry, something went wrong.
I assume this is agreeing with the half of my post saying that we couldn't actually remove getpath from libpython? It's unclear whether you're agreeing that removing getpath would break people who assume it'll be there or not, since more than half the quoted text is saying that it would break people if we actually did it. |
Sorry, something went wrong.
There was a problem hiding this comment.
(I'm currently reviewing the API at a high level from the docs only)
Sorry, something went wrong.
| Set an initialization callback. It allows executing code as soon as the | ||
| Python interpreter is initialized, before the first import. For example, it | ||
| can be used to add a meta path importer into :data:`sys.meta_path`. | ||
|
|
||
| When the callback is called, Python is only partially initialized. What's | ||
| available at this point: |
There was a problem hiding this comment.
"executing code as soon as the Python interpreter is initialized"
vs
"Python is only partially initialized. What's available ...:"
two different values of "initialized" here. That's a small list of what is available. Should we bother allowing people to call into Python at all or calling equivalent C Python C APIs from such an API? it feels maybe vaguely defined and hard to support and like something we might change the hyrum's law shape of what is available here?
Sorry, something went wrong.
There was a problem hiding this comment.
I changed the documentation to:
It allows executing code during the Python interpreter, before the first import.
Should we bother allowing people to call into Python at all or calling equivalent C Python C APIs from such an API?
Most of the C API is available when the callback is called, including PyRun_SimpleString() high-level function.
it feels maybe vaguely defined and hard to support and like something we might change the hyrum's law shape of what is available here?
It's vaguely defined on purpose, since the Python runtime is a complex beast, and it's hard to fully described its state while it's being initialized.
What can we do to make such API more future proof?
Sorry, something went wrong.
| A single callback can be registered. If this function is called more than | ||
| once, the previous callback is overridden. |
There was a problem hiding this comment.
We should probably start out by returning an error in this case. This is useful for embedding, it feels like multiple calls is always a bug until someone can make an argument otherwise.
Sorry, something went wrong.
There was a problem hiding this comment.
Ok, I modified the API to fail if it's called twice.
Sorry, something went wrong.
|
I updated my PR to address @gpshead's review. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Add init_callback and init_callback_arg members to PyConfig.
📚 Documentation preview 📚: https://cpython-previews--142420.org.readthedocs.build/