为什么Python的__import__需要fromlist?


问题内容

在Python中,如果要以编程方式导入模块,则可以执行以下操作:

module = __import__('module_name')

如果要导入子模块,您会认为这很简单:

module = __import__('module_name.submodule')

当然,这是行不通的。你只是module_name再次得到。你所要做的:

module = __import__('module_name.submodule', fromlist=['blah'])

为什么?fromlist只要它不是空的,它的实际值就似乎无关紧要。要求参数然后忽略其值的意义何在?

Python中的大多数内容似乎都是有充分理由的,但是出于我的一生,对于这种行为的存在,我无法提出任何合理的解释。


问题答案:

实际上,的行为__import__()完全是由于import调用的执行__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__()功能需要知道modmod2是名字的import声明都希望能够获得访问,以便它可以看到,如果他们是模块和尝试导入他们。因此,电话更接近:

tmp = __import__('pkg', fromlist=['mod', 'mod2'])
mod = tmp.mod
mod2 = tmp.mod2

这会导致__import__()尝试和负载pkg.modpkg.mod2以及pkg(但如果mod还是mod2不存在,它不是在错误__import__()的呼叫;产生一个错误是留给import。声明),但还不是第四和正确的事第五个示例,因为如果调用是这样的:

tmp = __import__('pkg.mod', fromlist=['submod'])
submod = tmp.submod

那么tmp最终将pkg像以前一样是,而不是pkg.modsubmod要从中获取属性的模块。该实现可能已经决定要这样做,所以该import语句会做更多的工作,.__import__()已经在函数中那样拆分程序包名称并遍历名称,但这将意味着重复一些工作。所以,相反,执行方面取得__import__()返回
最右边的 模块,而不是 最左边的 一个 当且仅当 fromlist里传递,而不是空。

import pkg as pandfrom pkg import mod as m语法对这个故事没有任何改变,只是将本地名称分配给了它-
使用该__import__()函数时as并没有什么不同,它们都保留在import语句实现中。)