I have a directory structure:
example.py
templates/
__init__.py
a.py
b.py
a.py and b.py have only one class, named the same as the file (because they are cheetah templates). For purely style reasons, I want to be able to import and use these classes in example.py like so:
import templates
t = templates.a()
Right now I do that by having this in the template folder's __init__.py:
__all__ = ["a", "b"]
from . import *
However, this seems pretty poor (and maybe superfluous), and doesn't even do what I want, as I have to use the classes like this:
t = templates.a.a()
Thoughts?
3 Answers 3
To avoid repeating from <whatever> import * 25 times, you need a loop, such as:
import sys
def _allimports(modnames)
thismod = sys.modules[__name__]
for modname in modnames:
submodname = '%s.%s' % (thismod, modname)
__import__(submodname)
submod = sys.modules[submodname]
thismod.__dict__.update(submod.__dict__)
_allimports('a b c d e'.split()) # or whatever
I'm putting the meaningful code in a function because (a) it's always best [[for performance and to avoid polluting the module's namespace]], (b) in this particular case it also avoids accidents (e.g., some submodule might define a name thismod or modnames... so it's important to keep those names that we're using in the loop local to the function, not module globals, so they can't be accidentally trampled;-).
If you want to enforce the fact that a module named modname only has one class (or other global) with the same name, change the last statement of the loop to:
setattr(thismod, modname, getattr(submod, modname))
3 Comments
a.py &c files with class a are (I believe) a Cheetah given, and asking users to always do from templates import a (&c) then use a.a() (&c) does feel somewhat redundant (I might go for it, but only because I'm an evangelist for "always import a module -- never a package, never anything from inside a module" and a sworn enemy of import *...;-) -- most people are more reasonable!-)template.py in lieu of the current template directory/package, that will be much simpler.In your __init__.py:
from a import *
from b import *
Now all of a's contents will be in templates, as will all of b's contents.
2 Comments
I didn't even know you could have from . import *. My python interpreter complains about such statements. Still, to your problem, you could do:
# __init__.py
from . import a, b
a = a.a
b = a.b
you can now use
# example.py
import templates
t = templates.a()
other solution:
# __init__.py
from a import *
from b import *