views:

54

answers:

2

At runtime, the Python code gets the name of a submodule to load, which I don't know before. Now, I want to check, if this submodule exists inside an existing module. Consider this structure, where foo and bar can be specified:

master/
|
|- __init__.py
|
|- foo/
|  |
|  |- __init__.py
|
|- bar/
   |
   |- __init__.py

Now, usually I do this, which works for defs and variables:

import master

unknown_submodule = "foo"
if hasattr(master, unknown_submodule):
    pass # all's well

or I'm catching the AttributeError, which works equally.

However, with the above file structure, I'm not able to bring this approach up and working. hasattr() returns always False (that is, there is always an AttributeError thrown).

If I look at dir(master), I see this output:

['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']

and even explicitly specifying __all__ in master/__init__.py doesn't help, but changes the dir() to

['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']

Any idea, what I'm doing wrong, or if there is a way to achieve these kinds of tests? (Btw: Python 2.6 on Win/Cygwin, if that's of any interest)

+1  A: 

you can do

try:
 import module.submodule

except ImportError:
  print 'failed or whatever'
damir
Yes, that works, thanks. However, do you know *why*?
Boldewyn
If `master/__init__.py` does not actively import `master.foo`, then `master` just has no member called `foo`. If you just import `master`, then `master.foo` raises an `AttributeError` regardless of whether `master.foo` exists.
Philipp
+1  A: 

Submodules are not attributes of their parent modules unless stated explicitly. Simply try to import the module and catch ImportError:

try:
    __import__("os.peth", fromlist=[os])
except ImportError:
    pass
Philipp
What do you mean with 'stated explicitly'? I thought, that's what `__all__` was for? Do you happen to have a pointer at hand for a useful explanation? (Other than http://docs.python.org/tutorial/modules.html or http://effbot.org/zone/import-confusion.htm )Apart from that, yes the `__import__()` does what is requested.
Boldewyn
No, `__all__` determines what gets imported when you say `from ... import *`. But this is not related to your problem. If you have a module `A` and a module `A.B`, then importing `A` does not magically add a member `B` to `A`—only if `A` itself imports `A.B`. To access `A.B` you have to import `A.B`, not `A`. In the case of `os.path` importing `os` works because `os` does actively import `os.path`.
Philipp
Thanks for the explanation! I think I start to get a grip on that matter.
Boldewyn