tags:

views:

88

answers:

2

Using the structure from the Python docs:

sound/
  __init__.py
  effects/
          __init__.py
          echo.py
          surround.py
          reverse.py

Say I want to import sound.effects and get a list of available effects. I could do this by declaring a module-level variable in sound.effects and then appending to it when each .py file is imported. So sound/effects/_init_.py might look like this:

effectList = []
import echo
import surround   # Could write code to import *.py instead
...

From my main code I can now access sound.effects.effectList to get a list of effects, but how do I access effectList from within echo.py to do the actual append? I'm stuck trying to get access to the variable:

# None of these work :-(
# from . import self
# from .. import effects
# import sound.effects

sound.effect.effectList.append({'name': 'echo'})
+1  A: 

I think you should leave the "making available" to the __init__.py inside the effects package rather than have all the modules auto populate the effectList. A couple of reasons I can think of.

  1. You can't import any of the effects except via the package if you did manage to get this work somehow (they'd except an effectList in the importing module).
  2. You have to manually do the append in every effect you write. It would be better if you just implemented an import *.py like thing in your __init__.py that loaded everything up in the current directory and made it available.

Something like this in your __init__.py.

import os, glob

effectslist = []

for i in glob.glob("*.py"):
    if i == "__init__.py":
        next
    print "Attempting to import %s"%i
    try:
        mod = __import__(os.path.splitext(i)[0])
        effectslist.append(mod)
    except ImportError,m:
        print "Error while importing %s - %s"%(i,m)
Noufal Ibrahim
Thanks for the quick reply. In my case it's not sound effects I'm wanting a list of, but static data (a bit like a poor man's database.) Since nobody will ever want to import just a single "effect" the resulting error is not really a problem. But I see your point about keeping things separate, maybe I should do all the appending in the init code. It'll be a bit messier but will keep each sub-module separate.
Malvineous
You might want to import effect by effect (e.g. for testing etc.). Te other pleasant effect is that all you need to get a new effect is to drop a file into this directory.
Noufal Ibrahim
+1  A: 

What people commonly do in this situation is create a common.py file in the module.

sound/
  __init__.py
  effects/
          __init__.py
          common.py
          echo.py
          surround.py
          reverse.py

Then you move the code from __init__.py to common.py:

effectList = []
import echo
import surround   # Could write code to import *.py instead
...

Inside __init__.py you have this:

from common import *

So now in echo.py you'd have this:

import common
common.effectList.append({'name': 'echo'})

Anything importing sound would use it like this

import sound.effect

for effect_name,effect in sound.effect.effectlist.items():
    #....

I've only just started using this myself, but I believe it's common practice in the python community.

Eric Palakovich Carr
Excellent, that worked perfectly! Many thanks. (Just FYI the for loop doesn't run as-is.)
Malvineous