tags:

views:

273

answers:

3

Sorry for the generic title, will change it once I understand the source of my problem I have the following structure:

foo/
foo/__init__.py
foo/bar/
foo/bar/__init__.py
foo/bar/some_module.py

When I try to import some_module by doing so:

from foo.bar import some_module

it works like a charm. But this is no good for me, since I only know the name of the module to import in runtime. so if I try:

from foo.bar import *
mod=__import__('some_module')

I get an error. Am I doing something wrong? Is there a better way to do this? and why is this happening?

Why is that? I am not quite sure I completely understand the concept behind python packages. I thought they were equivalent to java's packages and thus

+6  A: 

I believe the proper way to do this is:

mod = __import__('foo.bar', fromlist = ['some_module'])

This way even the 'foo.bar' part can be changed at runtime. As a result some_modulewill be available as mod.some_module; use getattr if you want it in a separate variable:

the_module = getattr(mod, 'some_module')
kurczak
A: 

From the docs:

Direct use of __import__() is rare, except in cases where you want to import a module whose name is only known at runtime.

However, the dotted notation should work:

mod = __import__('foo.bar.some_module')
ewall
+2  A: 
from foo.bar import *

is a bad practice since it imports some_module into the global scope.

You should be able to access your module through:

import foo.bar
mod = getattr(foo.bar, 'some_module')

It can be easily demonstrated that this approach works:

>>> import os.path
>>> getattr(os.path, 'basename')
<function basename at 0x00BBA468>
>>> getattr(os.path, 'basename\n')
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    getattr(os.path, 'basename\n')
AttributeError: 'module' object has no attribute 'basename
'

P.S. If you're still interested in using your kind of import statement. You need an eval:

from foo.bar import *
eval('some_module')

To clarify: not only it's bad practice to use *-import it's even worse in combination with eval. So just use getattr, it's designed exactly for situations like yours.

SilentGhost
-1 for recommending eval(). Always use globals()['some_module'] instead if all you want is to look up the value from global scope.
Daniel Pryden
All right, +1 again for your clarification. getattr() is the right answer here. If you need to use __import__(), see kurczak's answer.
Daniel Pryden
Uh oh, now I get "Vote too old to be changed, unless this answer is edited". My apologies -- I saw eval() in a code block and automatically clicked -1.
Daniel Pryden
sorry, this doesn't seem to work... doing this raise an error:'module' object has no attribute 'some_module' (Dunno why it refers to foo.bar as a module...)
noam
It works perfectly, it just means that `foo.bar` doesn't have attribute `some_module`. Where are you getting the name from?
SilentGhost
it works perfectly, if you add the line with getattr that's mentioned in kurczac's answer
noam
and you somehow missing the same line in my answer?
SilentGhost