2

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?

asked Jun 12, 2010 at 1:05

3 Answers 3

4

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))
answered Jun 12, 2010 at 1:56
Sign up to request clarification or add additional context in comments.

3 Comments

thanks! any thoughts on whether what I'm trying to do/what I have now is a good idea at all?
@colinmarc, I approve of your being skeptical about using such (deep) introspection / (slight) metaprogramming in production code, but you don't really have much of an alternative here -- the 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!-)
@colinmarc, sure, if you can have all the classes in a template.py in lieu of the current template directory/package, that will be much simpler.
3

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.

answered Jun 12, 2010 at 1:27

2 Comments

is there a way to do this without a line for each? I actually have like 25 templates
I'm a fan of simplicity. I wouldn't mind adding one line to init.py every time I added another module. Your taste may differ...
3

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 *
answered Jun 12, 2010 at 1:29

1 Comment

the "from . import..." is a relative import, which usually isn't a very good idea.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.