Lazy import in plugins?

John Arbash Meinel john at arbash-meinel.com
Sun Oct 8 08:49:56 BST 2006


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Stephen Ward wrote:
> Hi,
> 
> Is there a writeup anywhere on the changes needed to implement lazy import?  I 
> can probably glean this information from the email archive, and from the 
> details of some recent patches to bzr.dev, but I might overlook something 
> that way.
> 
> -- Steve
> 
> 

Well, it has always been possible to do something like:

from bzrlib.commands import Command, register_command


class cmd_foo(Command):

   def run(self, *args):
	from local_foo import actual_foo
        return actual_foo(*args)


register_command(cmd_foo)


This makes it so that plugins only import a minimum amount at startup
time, but 'local_foo' can import whatever it needs to get the job done.


If you actually want to use the 'lazy_import' module, you just do it like:

from bzrlib.lazy_import import lazy_import
lazy_import(globals(), """
import foo
import bar
from baz import wiki
...

from baz import (
  wiki as _wiki,
  foobar,
  )
""")

And from there, you can generally use them as though you did a real import.

The differences are:

1) When possible, avoid importing classes and functions in this way. It
still works as long as you *use* the object first. (As in foo.bar, or
foo(), etc)

2) Never import constants in this way, because you don't actually *use*
them in a manner than can be detected. (You don't call CONSTANT.foo or
CONSTANT() you just pass it around and compare against it)

3) Don't bind the imported objects to other variable names. So doing:

lazy_import(globals, """
from foo import bar
""")

baz = bar

Is a no-no. This is because the lazy imported objects are not proxies,
and are intentionally designed to not be proxies to avoid improper
usage. Specifically, they rebind the variable in the supplied scope to
the actual object that is imported. And if you use a different variable
name, we cannot detect this. It works the first time it is accessed,
because we can't detect it, but not on subsequent uses.

For example:

baz = bar
baz()
baz() # << this will fail

baz = bar
bar()
baz() # << this will fail

The worst one, though is that:

baz = bar
baz()
bar() # << this will fail because 'baz' stole the import.

The doc string in lazy_import() should give similar advice. And I
thought I added something to HACKING as well.

John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFFKK2kJdeBCYSNAAMRAk2nAJ0fKIbf90mrSXzbM33a8RR7NdnqjQCcDBAb
TgaNSyzcK0VGTM58MRzhNn4=
=9Hou
-----END PGP SIGNATURE-----




More information about the bazaar mailing list