Python与__import__和import之间的区别为

时间:2014-01-19 04:52:32

标签: python dynamic import

我正在尝试用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'>

我的问题是为什么差异?更重要的是,如何使动态导入示例与常规导入一样工作?

2 个答案:

答案 0 :(得分:6)

正如the documentation所解释的那样:

  

name 变量的格式为package.module时,通常会返回顶级包(直到第一个点的名称), not name 命名的模块。

所以,当你这样做时:

config = __import__("conf.config")

这与以下不一样:

import conf.config as config

而是更像是:

import conf.config
config = conf

为什么?

因为conf而非conf.config是受import语句约束的事物。 (当然,在import foo as bar中,显然bar受到限制......但__import__并不等同于import foo as bar,而是import foo。)文档进一步解释。但结果是你可能不应该首先使用__import__


在功能文档的最顶部,它说:

  

注意:这是日常Python编程中不需要的高级函数,与importlib.import_module()不同。

在底部,在解释了__import__如何使用包以及它为什么以这种方式工作之后,它说:

  

如果您只想按名称导入模块(可能在包中),请使用importlib.import_module()

因此,正如您可能猜到的,简单的解决方案是使用importlib.import_module


如果你必须使用Python 2.6,importlib不存在......好吧,只有 没有简单的解决方案。您可以在imp之外自己构建import_module之类的内容。或者使用__import__然后挖掘sys.modules。或__import__每件,然后getattr通过结果。或者以各种其他hacky方式。是的,这很糟糕 - 这就是3.0和2.7修复它的原因。

2.6文档举了第二个hack的例子。使其适应您的情况:

__import__("conf.config")
config = sys.modules["conf.config"]

答案 1 :(得分:0)

config = __import__("conf.config")不等同于import conf.config as config

例如:

>>> import os.path as path
>>> path
<module 'posixpath' from '/usr/lib/python2.7/posixpath.pyc'>

>>> __import__('os.path')
<module 'os' from '/usr/lib/python2.7/os.pyc'>

而不是__import__使用importlib.import_module来获取子包/子模块。

>>> import importlib
>>> importlib.import_module('os.path')
<module 'posixpath' from '/usr/lib/python2.7/posixpath.pyc'>