在Python中,如果要以编程方式导入模块,可以执行以下操作:
module = __import__('module_name')
如果你想导入一个子模块,你会认为它只是一个简单的问题:
module = __import__('module_name.submodule')
当然,这不起作用;你再次获得module_name
。你必须这样做:
module = __import__('module_name.submodule', fromlist=['blah'])
为什么? fromlist
的实际值似乎根本不重要,只要它不是空的。要求一个论点,然后忽略它的价值是什么意思?
Python中的大多数东西似乎都是有充分理由的,但对于我的生活,我无法对这种行为存在任何合理的解释。
答案 0 :(得分:121)
事实上,__import__()
的行为完全是因为调用import
的{{1}}语句的实现。 __import__()
可以调用__import__()
基本上有五种不同的方式(有两个主要类别):
import
在第一种和第二种情况下,import pkg
import pkg.mod
from pkg import mod, mod2
from pkg.mod import func, func2
from pkg.mod import submod
语句应将“最左侧”模块对象分配给“最左侧”名称:import
。在pkg
之后,您可以执行import pkg.mod
,因为pkg.mod.func()
语句引入了本地名称import
,这是一个具有pkg
属性的模块对象。因此,mod
函数必须返回“最左侧”模块对象,以便将其分配给__import__()
。因此,这两个进口声明转化为:
pkg
在第三,第四和第五种情况下,pkg = __import__('pkg')
pkg = __import__('pkg.mod')
语句必须做更多工作:它必须分配(可能)多个名称,它必须从模块对象获取。 import
函数只能返回一个对象,并且没有真正的理由让它从模块对象中检索每个名称(这会使实现变得更加复杂。)所以简单的方法就是喜欢(第三种情况):
__import__()
但是,如果tmp = __import__('pkg')
mod = tmp.mod
mod2 = tmp.mod2
是一个包而pkg
或mod
是该包中尚未导入的模块,则无效他们处于第三和第五种情况。 mod2
函数需要知道__import__()
和mod
是mod2
语句要访问的名称,以便它可以查看它们是否为模块并尝试也导入它们。所以电话更接近:
import
导致tmp = __import__('pkg', fromlist=['mod', 'mod2'])
mod = tmp.mod
mod2 = tmp.mod2
尝试加载__import__()
和pkg.mod
以及pkg.mod2
(但如果pkg
或mod
不加载mod2
存在,它不是__import__()
调用中的错误;产生错误留给import
语句。)但是对于第四和第五个例子来说仍然不是正确的,因为如果调用是这样的:
tmp = __import__('pkg.mod', fromlist=['submod'])
submod = tmp.submod
然后tmp
将像以前一样成为pkg
,而不是pkg.mod
模块,您想从中获取submod
属性。实现可能已经决定使import
语句执行额外的工作,将.
上的包名称与已经执行的__import__()
函数分开并遍历名称,但这意味着重复一些努力。相反,实现__import__()
返回最右侧模块而不是最左侧一个当且仅当时fromlist被传递而不是空。
(import pkg as p
和from pkg import mod as m
语法不会更改此故事的任何内容,除了分配了哪些本地名称 - __import__()
函数在as
时看不到任何不同使用时,它都保留在import
语句实现中。)
答案 1 :(得分:5)
当我阅读答案时,我仍感到很奇怪,所以我尝试了下面的代码示例。
首先,尝试构建以下文件结构:
tmpdir
|A
|__init__.py
| B.py
| C.py
现在A是package
,B
或C
是module
。所以当我们在ipython中尝试一些这样的代码时:
其次,在ipython中运行示例代码:
In [2]: kk = __import__('A',fromlist=['B'])
In [3]: dir(kk)
Out[3]:
['B',
'__builtins__',
'__doc__',
'__file__',
'__name__',
'__package__',
'__path__']
似乎fromlist按预期工作。但是,当我们尝试在module
上执行相同的操作时,事情会变得有线。假设我们有一个名为C.py的模块和代码:
handlers = {}
def hello():
print "hello"
test_list = []
所以现在我们尝试对它做同样的事情。
In [1]: ls
C.py
In [2]: kk = __import__('C')
In [3]: dir(kk)
Out[3]:
['__builtins__',
'__doc__',
'__file__',
'__name__',
'__package__',
'handlers',
'hello',
'test_list']
因此,当我们只想导入test_list时,它是否有效?
In [1]: kk = __import__('C',fromlist=['test_list'])
In [2]: dir(kk)
Out[2]:
['__builtins__',
'__doc__',
'__file__',
'__name__',
'__package__',
'handlers',
'hello',
'test_list']
结果显示,当我们尝试在module
而不是package
上使用fromlist时,fromlist参数根本没有帮助,因为已经编译了module
。一旦导入,就无法忽略其他的。
答案 2 :(得分:2)
答案可以在__import__
的文档中找到:
fromlist应该是要模拟
from name import ...
的名称列表,要么是用来模拟import name
的空列表。从包中导入模块时,请注意当fromlist为空时
__import__('A.B', ...)
返回包A,但当fromlist不为空时返回其子模块B.
基本上,这就是__import__
的实现如何工作:如果你想要子模块,你传递一个fromlist
包含你要从子模块导入的东西,以及{{1这样就会返回子模块。
进一步说明
我认为存在语义,以便返回最相关的模块。换句话说,我说包含__import__
的包foo
包含函数bar
。如果我:
baz
然后我将import foo.bar
称为
baz
这就像foo.bar.baz()
。
如果我导入:
__import__("foo.bar", fromlist=[])
然后我将from foo import bar
称为
bar.baz()
与baz
类似。
如果我这样做:
__imoort__("foo.bar", fromlist=["something"])
然后我将from foo.bar import baz
称为
baz
这就像baz()
。
所以在第一种情况下,我必须使用完全限定名称,因此__import__("foo.bar", fromlist=["baz"])
返回您用来引用导入元素的第一个模块名称,即__import__
。在最后一种情况下,foo
是包含导入元素的最具体模块,因此bar
返回__import__
模块是有意义的。
第二种情况有点奇怪,但我猜这是用支持使用foo.bar
语法导入模块的方式编写的,在这种情况下from <package> import <module>
仍然是最具体的模块。返回。