24

In my module, I have a couple of functions that depend on an external module with a long startup time. How do I use LazyLoader? If I have

import veggies

or

import veggies.brussels.sprouts

or

from veggies.brussels import sprouts

how would I replace those statements to use LazyLoader such that the execution of the contents of the module are postponed until needed?

It is not immediately obvious from the documentation how to use it. There is no example, and nullege code search only comes up with the unit test included with Python itself.

Azat Ibrakov
  • 9,998
  • 9
  • 38
  • 50
gerrit
  • 24,025
  • 17
  • 97
  • 170

1 Answers1

17

The original issue has some code that seems to to a full import lazily:

The following files imports two modules lazily:

import sys
import importlib.util

def lazy(fullname):
  try:
    return sys.modules[fullname]
  except KeyError:
    spec = importlib.util.find_spec(fullname)
    module = importlib.util.module_from_spec(spec)
    loader = importlib.util.LazyLoader(spec.loader)
    # Make module with proper locking and get it inserted into sys.modules.
    loader.exec_module(module)
    return module

os = lazy("os")
myown = lazy("myown")

print(os.name)
myown.test()

To test, I used the following in myown.py.

print("Executed myown.")
def test():
  print("OK")

That worked nicely (Python 3.8a0).

Petter
  • 37,121
  • 7
  • 47
  • 62
  • 1
    Can you show an example of how to actually use `LadyLoader`? – gerrit Jul 02 '18 at 09:46
  • The answer now contains a 100% complete working example. – Petter Jul 03 '18 at 11:15
  • 1
    I would suggest using loader = importlib.util.LazyLoader.factory(spec.loader) which also checks for the exec_module attribute. – throws_exceptions_at_you Feb 19 '19 at 15:31
  • Doesn't look like this answers the question though. Is there a way to make `import` statements lazy? – Suor Sep 10 '19 at 09:09
  • 1
    Another example use case is in https://www.mercurial-scm.org/repo/hg/file/tip/hgdemandimport/demandimportpy3.py – gps Nov 01 '19 at 03:29
  • This appears to work in CPython 3.5 through 3.10b4, perhaps later. – dstromberg Aug 17 '21 at 17:28
  • 3
    Current Python doc has a snippet - very similar! - for this which could be considered more canonical than this answer: https://docs.python.org/3/library/importlib.html#implementing-lazy-imports – creanion Dec 07 '21 at 12:11
  • There should be no need for that try block. `util.find_spec` already checks for `fullname` in `sys.modules`. https://docs.python.org/3/library/importlib.html#importlib.util.find_spec – Giuppox Jun 11 '23 at 08:56