-
-
Notifications
You must be signed in to change notification settings - Fork 30.1k
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
Removal of _PyImport_FindExtensionObject() in 3.10 limits custom extension module loaders #89470
Comments
https://bugs.python.org/issue41994 / commit 4db8988 removed _PyImport_FindExtensionObject() from the C API and it is no longer available in CPython 3.10 after alpha 5. At least py2exe and PyOxidizer rely on this API for implementing a custom module loader for extension modules. Essentially, both want to implement a custom Loader.create_module() so they can use a custom mechanism for injecting a shared library into the process. While the details shouldn't be important beyond "they can't use imp.create_dynamic()," both use a similar technique that hooks LoadLibrary() on Windows to enable them to load a DLL from memory (as opposed to a file). While I don't have the extension module loading mechanism fully paged in to my head at the moment, I believe the reason that _PyImport_FindExtensionObject() (now effectively import_find_extension()) is important for py2exe and PyOxidizer is because they need to support at most once initialization, including honoring the multi-phase initialization semantics. Since the state of extension modules is stored in I'm aware the deleted API was "private" and probably shouldn't have been used in the first place. And what py2exe and PyOxidizer are doing here is rather unorthodox. In my mind the simplest path forward is restoring _PyImport_FindExtensionObject(). But a properly designed public API is probably a better solution. Until 3.10 makes equivalent functionality available or another workaround is supported, PyOxidizer won't be able to support loading extension modules from memory on Windows on Python 3.10. This is unfortunate. But probably not a deal breaker and I can probably go several months shipping PyOxidizer with this regression without too many complaints. |
Gregory, could you please build Python 3.10 with PR 28594 applied and test whether py2exe and PyOxidizer work well with it? The restored function no longer used in the CPython code, so it is not tested now. |
I don't understand which long term solution do you propose.
Can you propose a public API? |
A kind reminder that for 3.10 we cannot add new APIs so this proposal still *makes sense* for the short term (3.10). |
py2exe maintainer here. In the end, did you define/propose a public API or any replacement API for this elimination? @indygreg |
If nobody asks for an API, no API is added. |
I don't believe I did. Since the deleted/private API was restored, it made my problem go away. I hadn't noticed that it was deleted in 3.11. So this will likely bit me/us again :/ |
As far as I understand your use case, I think you should have the necessary API for it. Please help me understand what I'm missing. I'm not clear on what “at most once initialization” means in your case. Is it at least once within a process? If so, would refusing repeated initialization within a process not work for you? I understand that for a generic module loader a simple global bool won't work, but a Python stores already-imported modules in |
I am not that familiar with Python internal procedures, could you tell me what process we should follow to ask for a new API?
Last year I did not start working on 3.10 in time, so I only started after the release and I did not even notice it was gone, thanks to your previous efforts (I did notice the deprecation warning, but it does not specify deletion in 3.11). Since we are again so late in the 3.11 release process, would it be absolutely preposterous to reintroduce Now a few notes about proposing a new API. In general, it is quite hard for me to advocate for it, as I am not entirely sure it is needed and what its purpose should be. Let's start with a recap of the This is my current understanding of the code but, please keep in mind this code was written 8 years ago, by somebody else, and even back then was largely inspired by the CPython implementation of the time (3.4). Also back then, the code contained a lot of calls to private CPython API so, it might be some decisions were taken based on the reference import implementation and never questioned, more than out of necessity. On this regard, it is worth to mention that this comment
is also present in the That being said, if we trust my understanding of the code, the use case could be as well satisfied by looking for EDIT: @encukou I realize now you proposed a similar approach while I was writing this paper, this kinda makes me more confident... |
This is due to the removal of _PyImport_FindExtensionObject from Python 3.11. As discussed in python/cpython#89470
This is due to the removal of _PyImport_FindExtensionObject from Python 3.11. As discussed in python/cpython#89470
This is due to the removal of _PyImport_FindExtensionObject from Python 3.11. As discussed in python/cpython#89470
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: