[Python-Dev] PEP: Post import hooks

Phillip J. Eby pje at telecommunity.com
Wed Jan 16 02:42:56 CET 2008


At 02:28 AM 1/16/2008 +0100, Christian Heimes wrote:
>Phillip J. Eby wrote:
> > At 10:14 PM 1/15/2008 +0100, Christian Heimes wrote:
> >> My code queues up new hooks while a sequence of hooks is processed. It
> >> makes sure that hooks for a parent aren't called in the middle of a
> >> child's hook chain.
> >
> > Notice that that's not necessary with the notification algorithm I gave,
> > since the list in post_import_hooks suffices as a queue.  So, just as in
> > peak.util.imports, the registration code doesn't need to know whether
> > callbacks are being run; it only needs to know whether they're *finished*.
>
>Are you sure your proposed algorithm and output match for the test case?
>I'm confident I got it right in C but I'm getting a different output.

I guess it's not right then.  ;-)  Though I shouldn't make fun, since 
it turns out that my code sketch was not a correct translation of 
peak.util.imports.  (See below.)


>Without the extra imp.notify_module_loaded('a.b') in func_a1(mod)::
>
>    ['func_a1', 'func_a2', 'func_ab1', 'func_ab2', 'func_ab3']
>
>
>With the extra imp.notify_module_loaded('a.b') in func_a1(mod)::
>
>    ['func_a1', 'func_ab1', 'func_ab2', 'func_ab3', 'func_a2']

Right - that's why I put it in there, to foil trivial implementations 
that don't really satisfy the invariant.


>I can't see how your implementation results in the first output when
>func_a1() calls the notification method.

Hm, you're right, my implementation sketch waits too long to set the 
__notified__ flag.  It should have read:

      def notify(name):
          try:
              module = sys.modules[name]
          except KeyError:
              raise ImportError("Module %s has not been imported" % (name,))
          if module.__notified__:
              return
          try:
              module.__notified__ = True
              if '.' in name:
                  notify(name[:name.rfind('.')])
              for callback in post_import_hooks[name]:
                 callback(module)
          finally:
              post_import_hooks[name] = None

That is, module.__notified__ has to be set *before* the recursive 
notification call.  This effectively happens in peak.util.imports 
now, except that __notified__ isn't an explicit attribute, just a 
side effect of other module state changes.


>I'm aware of the implications and my code already uses the lock. The
>PyImport_NotifyLoaded() method excepts to be called with the importer
>lock acquired. So I'm locking the importer lock in
>imp_notify_module_loaded(). The PyImport_RegisterPostImportHook() method
>does the locking before it accesses sys.modules and sys.post_import_hooks.

Great!



More information about the Python-Dev mailing list