-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
py/builtinimport.c: Allow built-in modules to be packages. #4731
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
Conversation
Note: I imagine that if |
It's not necessary in either case. Do it like CPython does: have C modules |
Note that there are quite a few test failures here, which would all need to be addressed.
Not for the core stuff because there's a RAM and execution overhead with frozen modules (creating and populating the outer dicts, at least).
This is possible but has overhead (as mentioned above). And if the goal is efficiency then it's sensible to provide the functionality in C. |
It's not sensible it implement more and more stuff in C, https://github.com/micropython/micropython/wiki/ContributorGuidelines has explicit warning against that. And for any feature implemented in C (== burdening the codebase and maintainers), there should be very good usecases. Example of one: to be able to compile arbitrary Python projects to native modules (which apparently would need to be done per-module), there should be support for packages in native modules. Sounds perfect, but support for native package imports would be the last and least important thing for that, first someone would need to present a compiler able to compile arbitrary Python code. But exactly as was mentioned, "native .mpy" is the closest thing en route to that aim, which supports those imports. As for "efficiency", this patch clearly adds overheads itself. And as everything implemented in C, it burdens everyone (and nobody needed packaged native imports for years). |
I'm also not sure the overhead of having C modules and .py package wrappers warrants this change? Isn't that a rather small overhead (in terms of performance I mean, or are we talking about some other overhead here?). And indeed this patch also introduces it's own overhead. And requiring a module to know it's own package name feels a bit too much 'the other way around' and not very flexible though on the other hand in practice this might never be an actual problem. |
cc1aa48
to
94fa8c6
Compare
Sorry about the test failures. I forgot that So the .py approach works (though it does have overheads of its own), I'm unsure where to put the .py files? For now I have it in But more than likely, this unumpy shouldn't need to live in the main repo, in which case I could do this as an external C module (as per #3871) but I still have the same problem with making it find the .py files. Finally, as I referenced above, the other option is to use dynamically loadable C code with the .mpy loaded from the filesystem (as per 81dee3e). I'm fairly sure I can make this work with the Fortran dependencies, but unless I'm mistaken, this isn't really an option for unumpy because all the native code from the .mpy file will be loaded into RAM? |
94fa8c6
to
aa26c70
Compare
+1 |
In terms of performance, it'd just be at import time, requiring an extra level of import, so not really much. But there is additional RAM usage holding the module dict of the .py wrapper module.
Yes that does look like it could be improved.
They could just live alongside the C code, and the easiest way to integrate them into a build is just for a port to include them in its list of frozen modules. Not ideal though because it's a manual process to include/exclude it depending if the C side of things exists or not. |
// go there. | ||
chop_component(this_name, &p); | ||
// take off another level. | ||
level++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a neat (albeit minor) code-space optimisation, which could be taken independent of this PR.
// https://docs.python.org/3/reference/import.html | ||
// "Specifically, any module that contains a __path__ attribute is considered a package." | ||
mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path))); | ||
size_t orig_path_len = path.len; | ||
vstr_add_char(&path, PATH_SEP_CHAR); | ||
vstr_add_str(&path, "__init__.py"); | ||
vstr_add_str(&path, PATH_SEP_CHAR_STR "__init__.py"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another good code-space optimisation which can be taken separately.
I'm unsure what you mean by "requiring a module to know it's own package name". Modules already knew their own name (via the |
As you say:
then suppose you add unumpy to the Python search path, you can |
The goal here is to make a built-in `unumpy`, and along with it `unumpy.fft` and `unumpy.linalg`. Two main changes: - Make built-in module importing happen as part of the dotted path walking as for regular modules. - Rather than making the submodule an attribute on the package (which can't be done on a built-in module), find them in `mp_loaded_modules_dict`. Note: to make this work, the built-in submodule sets its `__name__` to (e.g.) QSTR_unumpy_dot_fft, with corresponding Q(unumpy.fft) in qstrdefs. Note: This is gated by a new option MICROPY_MODULE_BUILTIN_PACKAGES.
aa26c70
to
c77f22d
Compare
Thanks for the explanation. That situation won't be handled -- it will always need to be imported as So I've pushed an update that hopefully is a reasonable compromise, depending on how you feel about config flags. With MICROPY_MODULE_BUILTIN_PACKAGES disabled, the code size is smaller on the three ports I tested:
With the flag enabled:
(Note: the 160 bytes is roughly equivalent to the cost of the frozen .py code anyway. I forget the exact number and I imagine it will grow as more of numpy is implemented) |
@jimmo I think this should be resolved as it was proposed in the original PR. This issue is no longer academic: we are facing the exact same problem with We already implemented |
Closing in favour of #5701 |
The goal here is to make a built-in
unumpy
, and along with itunumpy.fft
andunumpy.linalg
.Two main changes:
mp_loaded_modules_dict
.Note: to make this work, the built-in submodule sets its
__name__
to (e.g.)QSTR_unumpy_dot_fft
, with correspondingQ(unumpy.fft)
in qstrdefs.