[Python-Dev] PEP: Post import hooks (original) (raw)

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 postimporthooks 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.notifymoduleloaded('a.b') in funca1(mod)::

['funca1', 'funca2', 'funcab1', 'funcab2', 'funcab3']

With the extra imp.notifymoduleloaded('a.b') in funca1(mod):: ['funca1', 'funcab1', 'funcab2', 'funcab3', 'funca2']

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 funca1() 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 PyImportNotifyLoaded() method excepts to be called with the importer lock acquired. So I'm locking the importer lock in impnotifymoduleloaded(). The PyImportRegisterPostImportHook() method does the locking before it accesses sys.modules and sys.postimporthooks.

Great!



More information about the Python-Dev mailing list