Deferred imports

Justin Azoff justin.azoff at gmail.com
Fri Jul 14 21:57:54 EDT 2006


Tom Plunket wrote:
> I'm using this package that I can't import on startup, instead needing
> to wait until some initialization takes place so I can set other
> things up so that I can subsequently import the package and have the
> "startup needs" of that package met.
[...]
> So as y'all might guess, I have the solution in this sort of thing:
>
> import os
> global myDeferredModule
>
> class MyClass:
>    def __init__(self):
>       os.environ['MY_DEFERRED_MODULE_PARAM'] = str(self)
>       global myDeferredModule
>       import myDeferredModule
>
> m = MyClass()
>
> HOWEVER, my problem now comes from the fact that other modules need to
> use this import.  So, I need to either use the above "trick", or I
> need to just import the module in every function that needs it (which
> will be almost exclusively the constructors for the objects as they're
> the ones creating Pygame objects).
>
> So my question is, is 'import' heavy enough to want to avoid doing it
> every time an object is created, or is it fairly light if it's
> currently active somewhere else in the application?  I suppose that
> may depend on how many objects I'm creating, and how frequently I'm
> creating them, but if 'import' resolves to essentially
>
> if not global_imports.has_key(module):
>    do_stuff_to_import_module

Importing a module repeatedly certainly won't help the application run
any _faster_, but you may not notice the difference.  Especially if
this particular block of code does not run in a tight loop.  It does
work like you described, the specific dictionary is sys.modules:

>>> print file('a.py').read()
print "THIS IS A!"
>>> 'a' in sys.modules
False
>>> import a
THIS IS A!
>>> 'a' in sys.modules
True
>>> import a #will not execute a.py again
>>>

> ...then I'm not so worried about putting it into every constructor.
> Otherwise I'll do this trick, starting myDeferredModule = None and
> only do the import if not None.

The extra check for not None probably wouldn't be much faster than the
check import does in sys.modules.  Just calling import in the
constructor will also be easier for someone else to understand :-)

> Thanks!
>
> -tom!

pypy has a neat lazy loading importer, you could see how they implement
it, I think it is just something like

class defer:
    def __getattr__(self, attr):
        return __import__(attr)
defer = defer()

then defer.foo will import foo for you.

-- 
- Justin




More information about the Python-list mailing list