0

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)

Boldewyn
  • 81,211
  • 44
  • 156
  • 212

3 Answers3

2

I recently had to check submodule existence and since I'm using python 3.4.1, I'm giving a new answer to the question:

In python 3.4.1 you can use importlib.util.find_spec(name, package=None) (https://docs.python.org/3.4/library/importlib.html#importlib.util.find_spec)

import importlib
module_exists = importlib.util.find_spec('path.to.my.module')

That easy =)

valentin
  • 2,596
  • 6
  • 28
  • 48
2

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
  • 48,066
  • 12
  • 84
  • 109
  • 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 Jul 13 '10 at 13:15
  • 1
    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 Jul 13 '10 at 13:50
  • Thanks for the explanation! I think I start to get a grip on that matter. – Boldewyn Jul 13 '10 at 14:11
1

you can do

try:
 import module.submodule

except ImportError:
  print 'failed or whatever'
damir
  • 428
  • 2
  • 10
  • 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 Jul 13 '10 at 13:54