1

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

SilentGhost
  • 307,395
  • 66
  • 306
  • 293
olamundo
  • 23,991
  • 34
  • 108
  • 149

3 Answers3

7

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
  • 1,521
  • 1
  • 10
  • 18
1
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
  • 307,395
  • 66
  • 306
  • 293
  • -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 Aug 27 '09 at 16:42
  • 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 Aug 27 '09 at 16:48
  • 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 Aug 27 '09 at 16:49
  • 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...) – olamundo Aug 27 '09 at 16:55
  • It works perfectly, it just means that `foo.bar` doesn't have attribute `some_module`. Where are you getting the name from? – SilentGhost Aug 27 '09 at 16:58
  • it works perfectly, if you add the line with getattr that's mentioned in kurczac's answer – olamundo Aug 29 '09 at 05:49
  • and you somehow missing the same line in my answer? – SilentGhost Aug 29 '09 at 09:39
0

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')
SilentGhost
  • 307,395
  • 66
  • 306
  • 293
ewall
  • 27,179
  • 15
  • 70
  • 84