我正在尝试在 Python 中动态导入配置文件。
我的代码在我使用时工作正常:
import conf.config as config
但是当我使用时不能正常工作:
config = __import__("conf.config")
下面是示例程序和运行它们时得到的结果:
#regularimport.py
import conf.config as config
def read_values(cfg):
for varname in cfg.__dict__.keys():
if varname.startswith('__'):
continue
value = getattr(cfg, varname)
yield (varname, value)
for name,value in read_values(config):
print "Current config: %s = %s" % (name, value)
结果:
$python regularimport.py
Current config: SETTING_TWO = another setting
Current config: SETTING_ONE = some setting
动态导入:
#dynamicimport.py
conf_str = "conf.config"
config = __import__(conf_str)
def read_values(cfg):
for varname in cfg.__dict__.keys():
if varname.startswith('__'):
continue
value = getattr(cfg, varname)
yield (varname, value)
for name,value in read_values(config):
print "Current config: %s = %s" % (name, value)
结果:
$ python dynamicimport.py
Current config: config = <module 'conf.config' from '/home/ubuntu/importex/conf/config.pyc'>
我的问题是为什么不同?更重要的是,如何使动态导入示例像常规导入一样工作?
最佳答案
作为the documentation解释:
When the name variable is of the form
package.module
, normally, the top-level package (the name up till the first dot) is returned, not the module named by name.
所以,当你这样做时:
config = __import__("conf.config")
这不同于:
import conf.config as config
而是更像是:
import conf.config
config = conf
为什么?
因为 conf
,而不是 conf.config
,是被 import
语句绑定(bind)的东西。 (当然,在 import foo as bar
中,显然 bar
被绑定(bind)了……但是 __import__
并不等同于 import foo as bar
,但是 import foo
。)文档进一步解释。但结果是您可能一开始就不应该使用 __import__
。
在函数文档的最顶部,它说:
Note: This is an advanced function that is not needed in everyday Python programming, unlike
importlib.import_module()
.
在底部,在解释了 __import__
如何与包一起工作以及为什么这样工作之后,它说:
If you simply want to import a module (potentially within a package) by name, use
importlib.import_module()
.
因此,正如您可能猜到的那样,简单的解决方案是使用 importlib.import_module
.
如果您必须使用 Python 2.6,其中 importlib
不存在……好吧, 没有简单的解决方案。你可以用 imp
自己构建类似 import_module
的东西.或者使用 __import__
然后挖掘 sys.modules
。或者 __import__
每个片段,然后 getattr
以您的方式处理结果。或者以其他各种骇人听闻的方式。是的,这很糟糕——这就是 3.0 和 2.7 修复它的原因。
2.6 文档给出了第二个 hack 的示例。根据您的情况进行调整:
__import__("conf.config")
config = sys.modules["conf.config"]
关于__import__ 和 import as 之间的 Python 区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21213355/