[Python-ideas] LOAD_NAME/LOAD_GLOBAL should be use getattr()
nas-python-ideas at arctrix.com
Tue Sep 12 12:17:08 EDT 2017
This is my idea of making module properties work. It is necessary
for various lazy-loading module ideas and it cleans up the language
IMHO. I think it may be possible to do it with minimal backwards
compatibility problems and performance regression.
To me, the main issue with module properties (or module __getattr__)
is that you introduce another level of indirection on global
variable access. Anywhere the module.__dict__ is used as the
globals for code execution, changing LOAD_NAME/LOAD_GLOBAL to have
another level of indirection is necessary. That seems inescapable.
Introducing another special feature of modules to make this work is
not the solution, IMHO. We should make module namespaces be more
like instance namespaces. We already have a mechanism and it is
getattr on objects.
I have a very early prototype of this idea. See:
Issues to be resolved:
- __namespace__ entry in the __dict__ creates a reference cycle.
Maybe could use a weakref somehow to avoid it. Maybe we just
explicitly break it.
- getattr() on the module may return things that LOAD_NAME and
LOAD_GLOBAL don't expect (e.g. things from the module type). I
need to investigate that.
- Need to fix STORE_* opcodes to do setattr() rather than
- Need to optimize the implementation. Maybe the module instance
can know if any properties or __getattr__ are defined. If no,
have __getattribute__ grab the variable directly from md_dict.
- Need to fix eval() to allow module as well as dict.
- Need to change logic where global dict is passed around. Pass the
module instead so we don't have to keep retrieving __namespace__.
For backwards compatibility, need to keep functions that take
'globals' as dict and use PyModule_GetDict() on public APIs that
return globals as a dict.
- interp->builtins should be a module, not a dict.
- module shutdown procedure needs to be investigated and fixed. I
think it may get simpler.
- importlib needs to be fixed to pass modules to exec() and not
dicts. From my initial experiments, it looks like importlib gets
a lot simpler. Right now we pass around dicts in a lot of places
and then have to grub around in sys.modules to get the module
object, which is what importlib usually wants.
I have requested help in writing a PEP for this idea but so far no
one is foolish enough to join my crazy endeavor. ;-)
More information about the Python-ideas