[Python-ideas] Modules as global namespaces rather than dicts

Neil Schemenauer nas-python-ideas at arctrix.com
Tue Nov 14 15:34:07 EST 2017

This is an idea I have been playing with and seems to hold some
promise.  I think we should use a module instance as the standard
global namespace rather than directly using its dict.  I have a
prototype version of CPython that does this, not working 100% yet

Major changes:

- In the frameobject, remove f_builtins and f_globals, add
  f_namespace that refers to the module.  Make f_globals and
  f_builtins into properties.

- Change ceval to use f_namespace, rather than carrying around
  globals and builtins.  Change functions that take globals as a
  dict so they also accept a module object.

- Change the module object to keep track of the builtins for it.

- Change funcobject (e.g. PyFunction_NewWithQualName) to
  accept 'globals' as a module object

- When given a dict and we now expect a module object, create an
  anonymous module to wrap it.  This part is a bit tricky due to
  reference cycles and speed requirements.  However, my hope is that
  if the internals of CPython can be made to pass modules instead of
  dicts around, these anonymous modules will become a rare case and
  so won't matter if they are a little slower.

So, what is the purpose of all this trouble?

- I believe quite a lot of Python internals can be simpler.  For
  example, importlib is complicated by the fact that a dict is
  passed around when most of the logic would prefer to have the
  module.  Grubbing in sys.modules to lookup the module object is
  ugly.  The expression "exec(code, module)" is elegant to me.

- I believe it will be possible to make global variable access work
  similar to fast locals.  I.e. have each module contain a indexed
  list of global names, and use an array lookup rather than a dict
  lookup in the normal case.  For backwards compatibility, my idea
  is to keep a flag on the module object noting if fast global
  behavior is okay.  If someone grabs the module dict, e.g. using
  module.__dict__ , vars() or frame.f_globals then we clear the flag
  and revert to the slow dict behavior.  Also, if a piece of code is
  executed in a different namespace, we have to revert to the slow
  case.  That does not seem so hard to do.

- I want to have properties for module globals and have them work
  from within the module.  I.e. changing something from a global
  variable to a property should not require changes to other module
  code.  I.e. LOAD_GLOBAL should trigger a property get.



More information about the Python-ideas mailing list