关于python和__import__的问题
抱歉标题有点普通,等我搞清楚问题的来源再改。
我有以下的结构:
foo/
foo/__init__.py
foo/bar/
foo/bar/__init__.py
foo/bar/some_module.py
当我尝试通过下面的方式导入某个模块时:
from foo.bar import some_module
这就能顺利运行。
但这样对我来说不太好,因为我只能在运行时知道要导入哪个模块。所以如果我尝试:
from foo.bar import *
mod=__import__('some_module')
我就会遇到错误。我是不是做错了什么?有没有更好的方法?为什么会这样?
这是为什么呢?我不太确定我完全理解Python包的概念。我原以为它们和Java的包是一样的,所以……
3 个回答
0
来自文档的内容:
直接使用
__import__()
的情况很少,通常只有在你想导入一个名字在运行时才知道的模块时才会用到。
不过,使用点号的方式应该是可以的:
mod = __import__('foo.bar.some_module')
1
from foo.bar import *
这样做是不好的习惯,因为它把 some_module
导入到了全局范围内。
你应该通过以下方式来访问你的模块:
import foo.bar
mod = getattr(foo.bar, 'some_module')
这个方法的有效性很容易证明:
>>> 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
'
附言:如果你仍然想使用你那种导入语句,你需要用到 eval
:
from foo.bar import *
eval('some_module')
为了说明:不仅仅是使用 *
导入是不好的习惯,和 eval
一起使用更是糟糕。所以就用 getattr
吧,它正是为你这种情况设计的。
7
我认为正确的做法是:
mod = __import__('foo.bar', fromlist = ['some_module'])
这样做的话,即使是 'foo.bar' 这一部分也可以在运行时进行更改。
这样一来,some_module
就可以作为 mod.some_module
来使用;如果你想把它放在一个单独的变量里,可以使用 getattr:
the_module = getattr(mod, 'some_module')