[Python-ideas] Idea to support lazy loaded names.

Brian Allen Vanderburg II brianvanderburg2 at aim.com
Tue Oct 7 03:34:16 CEST 2014


When developing Python libraries (and any other language for that
matter), items are separated into modules for organization and other
purpose.  The following is an example fake framework to illustrate this:

  mini-framework/
    __init__.py
    app.py
      class BaseApplication
      class Application
      class ProxyApplication
    config.py
      class Config
      class ConfigLoader
    template.py
      class Template
      class TemplateCompiler
      class TemplateManager

In order to be used externally, one must reference the module:

  from miniframework.app import Application
  from miniframework.template import TemplateManager

This can be solved by importing these values directly in __init__.py.
However this requires fully loading those imported modules:

  __init__.py:
    from .app import BaseApplication, Application, ProxyApplication
    from .config import Config, ConfigLoader
    from .template import Template, TemplateCompiler, TemplateManager
  
One idea I had was to support lazy imported names.  I've seen some
frameworks implement this in various means, and figured the idea is good
to be part Python.

The idea is that for a new module attribute to exist: __lazyload__.
During the access of any attribute for a module, the following would
happen:

  * If the named attribute already exists, use it
  * If the named attribute does not already exist:
    * If a lazy load of the name has already been attempted, result in
      a NameError
    * If a lazy load of the name has not yet been attempted:
       * Check the __lazyload__ module attribute for the name, perform
         the loading operation and assign the module attribute the
         value if found or result in a NameError
       * Even if not found, set a flag that lazy load has been
         attempted so it will not be attempted again for the same name

The __lazyload__ attribute is intended to be a dictionary.  The key of
the dictionary is the name of the attribute that would be set/tested
for in the module.  The value of the dictionary is a string that
represents either the module name to load or the module name and
attribute to load.  If the value starts with a dot, then it is treated
as a relative import relative to the module/package containing the
__lazyload__ value.

With this idea, the packages __init__.py file could look like this:

  __lazyload__ = {
    'BaseApplication': '.app.BaseApplication',
    'Application': '.app.Application',
    ...
  }
       
The end use of the package (and even the developer) can then perform an
import as follows:

  from miniframework import Application

instead of:

  from miniframework.app import Application

This allows the public api be be cleaner, while still being efficient
by not loading all modules in __init__.py until the value is actually
accessed.



Brian Allen Vanderburg II


More information about the Python-ideas mailing list