Lazy module variables--can it be done?

itunes, lazy-loading, module, python, variables

Solution

You can't do it with modules, but you can disguise a class "as if" it was a module, e.g., in `itun.py`, code...:

import sys

class _Sneaky(object):
  def __init__(self):
    self.download = None

  @property
  def DOWNLOAD_PATH(self):
    if not self.download:
      self.download = heavyComputations()
    return self.download

  def __getattr__(self, name):
    return globals()[name]

# other parts of itun that you WANT to code in
# module-ish ways

sys.modules[__name__] = _Sneaky()

Now anybody can `import itun`... and get in fact your `itun._Sneaky()` instance. The `__getattr__` is there to let you access anything else in `itun.py` that may be more convenient for you to code as a top-level module object, than inside `_Sneaky`!_)

Problem

I'm trying to find a way to lazily load a module-level variable. Specifically, I've written a tiny Python library to talk to iTunes, and I want to have a `DOWNLOAD_FOLDER_PATH` module variable. Unfortunately, iTunes won't tell you where its download folder is, so I've written a function that grabs the filepath of a few podcast tracks and climbs back up the directory tree until it finds the "Downloads" directory. This takes a second or two, so I'd like to have it evaluated lazily, rather than at module import time. Is there any way to lazily assign a module variable when it's first accessed or will I have to rely on a function?

Original source