从字符串变量导入模块


182

我正在编写有关matplotlib(MPL)嵌套库的文档(个人),该文档与感兴趣的子模块包所提供的MPL有所不同。我正在编写Python脚本,希望该脚本可以自动从将来的MPL版本中生成文档。
我选择了感兴趣的子模块/程序包,并希望列出其主要类,然后从中生成列表并进行处理。pydoc

问题是我找不到指示Python从字符串加载子模块的方法。这是我尝试过的示例:

import matplotlib.text as text
x = dir(text)

i = __import__('matplotlib.text')
y = dir(i)

j = __import__('matplotlib')
z = dir(j)

这是通过pprint比较上述列表的三种方式:

在此处输入图片说明

我不明白y对象中加载了什么-它是基础对象matplotlib以及其他内容,但是它缺少我想要的信息,而这正是matplotlib.text包中的主要类。它是屏幕截图中最上面的蓝色部分(x列表)

请不要建议Sphinx作为其他方法。


您能解释为什么需要使用__import__(str)而不是标准importstatemetn吗?
thesamet 2012年

这是因为我将处理列出哪些项是MPL子模块并获取其方法路径
theta 2012年

9
@thesamet-来吧-有很多想法需要使用此功能。当您具有库的文本配置时,可以按名称加载它们,这与该import语句不太兼容。这是一个使用示例:djangosnippets.org/snippets/3048
Tomasz

Answers:


278

__import__功能可能有点难以理解。

如果你改变

i = __import__('matplotlib.text')

i = __import__('matplotlib.text', fromlist=[''])

然后i将参考matplotlib.text

在Python 2.7和Python 3.1或更高版本中,可以使用importlib

import importlib

i = importlib.import_module("matplotlib.text")

一些注意事项

  • 如果您尝试从子文件夹(例如)中导入内容./feature/email.py,则代码将如下所示importlib.import_module("feature.email")

  • 如果__init__.py您要导入的文件所在的文件夹中没有任何内容,则无法导入任何内容


3
importlib应该在pypi上适用于<python2.7
Jeffrey Jose

49
对于任何来自Google的人。应该注意的是,如果您尝试从子文件夹中导入某些内容(例如./feature/email.py),则代码将类似于importlib.import_module("feature.email")
Seanny123

11
最后,还要记住,如果__init__.py要导入的文件所在的文件夹中没有任何内容,则无法导入任何内容。
Seanny123

3
@mzjn这用于import moduleNamemoduleName是字符串的地方。怎么from moduleName import *
Nam G VU's

2
我的问题在这里刚刚找到答案,以防万一有人需要它stackoverflow.com/a/31306598/248616
Nam G VU

68

importlib.import_module是您要寻找的。它返回导入的模块。(仅适用于Python> = 2.7或3.x):

import importlib

mymodule = importlib.import_module('matplotlib.text')

之后,您可以访问模块中的任何内容mymodule.myclass,例如等等。



5
@gecco这是import moduleName其中moduleName是字符串的地方。怎么from moduleName import *
Nam G VU's

6

花了一些时间尝试从列表中导入模块,而这正是使线程到达我那里的大部分方式-但是我不了解___import____的用法-

因此,这是从字符串导入模块并获得与导入相同的行为的方法。并尝试/排除错误情况。:)

  pipmodules = ['pycurl', 'ansible', 'bad_module_no_beer']
  for module in pipmodules:
      try:
          # because we want to import using a variable, do it this way
          module_obj = __import__(module)
          # create a global object containging our module
          globals()[module] = module_obj
      except ImportError:
          sys.stderr.write("ERROR: missing python module: " + module + "\n")
          sys.exit(1)

是的,对于python 2.7>,您还有其他选择-但是对于2.6 <,这可行。


1

我开发了以下3个有用的功能:

def loadModule(moduleName):
    module = None
    try:
        import sys
        del sys.modules[moduleName]
    except BaseException as err:
        pass
    try:
        import importlib
        module = importlib.import_module(moduleName)
    except BaseException as err:
        serr = str(err)
        print("Error to load the module '" + moduleName + "': " + serr)
    return module

def reloadModule(moduleName):
    module = loadModule(moduleName)
    moduleName, modulePath = str(module).replace("' from '", "||").replace("<module '", '').replace("'>", '').split("||")
    if (modulePath.endswith(".pyc")):
        import os
        os.remove(modulePath)
        module = loadModule(moduleName)
    return module

def getInstance(moduleName, param1, param2, param3):
    module = reloadModule(moduleName)
    instance = eval("module." + moduleName + "(param1, param2, param3)")
    return instance

每次我想重新加载新实例时,都只需要像这样调用getInstance()即可:

myInstance = getInstance("MyModule", myParam1, myParam2, myParam3)

最后,我可以调用新实例中的所有函数:

myInstance.aFunction()

这里唯一的特殊性是自定义实例的参数列表(param1,param2,param3)。


1

除了使用importlib一个,还可以使用exec方法从字符串变量导入模块。

在这里,我展示了使用combinations方法从itertools包中导入方法的示例exec

MODULES = [
    ['itertools','combinations'],
]

for ITEM in MODULES:
    import_str = "from {0} import {1}".format(ITEM[0],', '.join(str(i) for i in ITEM[1:]))
    exec(import_str)

ar = list(combinations([1, 2, 3, 4], 2))
for elements in ar:
    print(elements)

输出:

(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.