[Python-3000] Interest in PEP for callbacks on module import

Phillip J. Eby pje at telecommunity.com
Fri Dec 7 15:35:17 CET 2007


At 12:33 PM 12/7/2007 +0100, Christian Heimes wrote:
>Nick Coghlan wrote:
> > For example, to handle the commented out case above:
> >
> >    @imp.imported('decimal')
> >    def register(decimal):
> >        Inexact.register(decimal.Decimal)
>
>I like the syntax assuming that imp.imported(name) expects a method that
>accepts the module object as argument.

I prefer something like 'when_imported' or 'upon_import' or something 
else that more specifically refers to the idea that this is 
registering a handler to be called.  imported() by itself sounds like 
a query as to whether the module is currently imported.


> > I think a PEP would be needed to decide whether to handle this in a
> > fashion similar to that of PJE's Importing toolkit [1] (i.e., using lazy
> > imports where the actual loading of the module code is deferred until
> > the first access to an attribute of the module), or else to add a new
> > mechanism directly to the interpreter code, where the registered
> > callbacks would be called as soon as the specified module was loaded.
>
>I find a new mechanism easier to implement. Lazy or deferred imports
>require frame hacks

No, they don't.  See:

http://svn.eby-sarna.com/Importing/peak/util/imports.py?view=markup

The mechanism I used is to create a subclass of ModuleType and put it 
in sys.modules as a placeholder for the "real" module.  When the 
module is touched, I effectively change the type back to a regular 
module, and call reload() to actually import the module.

Of course, since Python 2.3 (this code was originally written for 
2.2), you can't change a subclass of ModuleType back to ModuleType 
itself, so I actually change the custom subclass on the fly.  This is 
easy enough to do in Python, but I'd hate to do it in C.

If I were doing it in C, I'd just add a laziness flag and callback 
list to the base ModuleType.  The tp_getattro could then check the 
laziness flag and do the rest.



> > Does anyone else think this is an issue worth pursuing?

A qualified yes: the Importing package took a long time to get 
correct under all the crazy little twists and turns of importing, 
including correctly handling things like the link between packages 
and their child packages/modules, the import order of same, race 
conditions, import locks, clearing out callbacks, etc.  I'm somewhat 
hesitant as to whether a from-scratch reimplementation is wise.

I'm also concerned about interoperability.  If you add the equivalent 
of Importing's whenImported, but not lazyModule, then I'll still need 
Importing itself -- and the builtin implementation of whenImported 
might conflict with lazyModule.  In particular, the builtin 
when_imported might confuse a lazyModule with something that's 
already imported, and fire off callbacks when it shouldn't.

So, I vote for making module laziness part of the implementation, if 
there is one.

There also should be APIs provided by imp to inspect (or change) the 
laziness of a module without causing it to become un-lazy.  This is 
needed so that other ModuleType subclasses can play too.  For 
example, some tools use ModuleType subclasses to implement 
attribute-level laziness instead of whole-module laziness.

There may be other interop issues with libraries that use ModuleType 
subclasses or do lazy import, deprecation, and similar module content 
manipulation, so a publicized PEP would be a good idea to get their 
developers' input.



More information about the Python-3000 mailing list