New approach to lazy loading of pygame submodules (surfarray
, sndarray
)
#3249
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
A new approach to lazy loading pygame submodules after #3232 had a problem with slower attribute accesses (
__getattr__
).Implementation explanation:
The implementation is twofold, where the second part has many alternatives.
First, pygame checks if
numpy
exists.Then, each submodule is loaded if numpy exists and the submodule's other pygame module dependencies (e.g.
mixer
) load successfully. If numpy is missing or a module dependency fails, then the submodule becomesMissingModule
. It is necessary to get an error to use its message inMissingModule.reason
, sotry-except
is used.If successful, the submodule is created and put into
sys.modules
, using the documentedLazyLoader
implementation, relying on import machinery.This makes it so that the submodule exists, but its contents are not executed until the first attribute or method access on the submodule.
It does this by changing the module class temporarily to
_LazyModule
; after the module is actually loaded, the module class is set back to the normal module type.Potential differences from current behavior:
The initial checks are not completely perfect. It is assumed that if
numpy
is importable, it will not raise anImportError
norOSError
.Obviously,
numpy
not being loaded by pygame automatically is an intended difference. Instead, it is loaded upon the first attribute access of either submodule. I do not expect this to cause any lag spikes in-game: the user probably imports numpy themselves, and it will also load if directly importing one of the submodule functions, or using one during game loading.After a submodule is loaded successfully, there should not be any noticeable difference from current behavior. The module class is the same, the original loader is put back, the module code was not changed.
https://docs.python.org/3/library/importlib.html#importlib.util.LazyLoader
There are no expected errors during postponed loading of these submodules, as they should have all been handled at the start.
Lazy loading of numpy has great potential benefits, so it's worth the extra complexity.
Closes #3232