[Python-Dev] PEP: Post import hooks

Phillip J. Eby pje at telecommunity.com
Thu Jan 10 23:32:28 CET 2008


At 09:40 PM 1/10/2008 +0100, Christian Heimes wrote:
>Phillip J. Eby wrote:
>[...]
>
> > There's also one twist that I haven't sorted out yet: "Importing"
> > guarantees that a parent module 'foo' will have a 'bar' attribute for
> > the 'foo.bar' module, if 'foo.bar' is lazy.  It does this by
> > registering a callback, ideally *before* any other callback is
> > registered for 'foo' or 'foo.bar' that would look at 'foo.bar'.  I
> > don't see how to maintain this condition in a world where import
> > callbacks can be registered independently.
>
>I've moved the PyImport_NotifyModuleLoaded() call to import_submodule().
>It (should) guarantee that the hooks for a parent package is called
>before the hooks for its children are called. I've analyzed the code
>carefully enough to be sure but all unit test results are on my side.
>
>On other words "import a.b.c" fires the hooks for "a", then "a.b" and at
>last "a.b.c".

Yes, that's the general idea.  But what happens if you are in the 
middle of firing hooks for 'a', and a new hook for 'a.b.c' is 
added?  What about a new hook for 'a'?


>I could also modify imp.notify_module_loaded to accepts the module name
>as string ("a.b.c."). If the module is provided by name (e.g. "a.b.c.")
>rather than by object it makes sure that the hooks for "a", "a.b" and
>"a.b.c" are called in the right order.

Well, it certainly can (and should) do the same if a module object is 
provided, since the module has a __name__.


>Would the modification fulfill your needs if
>imp.notify_module_loaded("foo.bar.baz") call the hooks for "foo",
>"foo.bar" and "foo.bar.baz" in that order?

Only if you can guarantee that no hook for a submodule is run until 
all the parent hooks are finished being called *and* that adding new 
callbacks while callbacks are being run will still call them... 
*after* any already-added callbacks.


>The initial design used to set the hooks to None *after* the hooks were
>called. I removed code yesterday because I thought it's not required.
>Today I've re-added the checks for Py_None.

In general, if you think something in peak.util.imports isn't 
required, you're probably wrong.  ;)


>I'm not setting the hooks to Py_None before the hook are called.

That's fine, but here's a different catch: are you iterating over the 
hooks by taking the length before you start?  If so, then hooks that 
are added *while* the hooks are being called back, will never get 
called, because they'll be added to the end of the list (and you'll 
never reach the end).  Make sure there's a test for that case.

peak.util.imports sets to None after callbacks, but it uses regular 
list iteration, so hooks can be added to the end of the list while 
the hooks are still being called.

An error while running the hooks should also set the hook list to 
None and discard all the hooks.  There isn't any sane way to recover 
from an error in a post-import hook.



More information about the Python-Dev mailing list