代码之家  ›  专栏  ›  技术社区  ›  Ian Baget

python模块的动态加载

  •  3
  • Ian Baget  · 技术社区  · 15 年前

    我正在尝试动态加载我创建的模块。

    现在这项工作正常:

    import structures.index
    

    但如果我通过动态导入来尝试相同的操作,它就会失败。

    struct = __import__("structures.index")
    

    提供的错误是:

    Error ('No module named structures.index',)
    

    有什么想法吗?


    编辑:使用全范围时(它是一种工作?):

    struct = __import__("neoform.structures.index")
    

    这不会引发任何错误,但是,它没有加载索引模块,而是加载“新形式”模块。

    “struct”的结果是:

    <module 'neoform' from '/neoform/__init__.py'>
    

    另外,作为一个附带问题,我如何在动态加载的模块中实例化类?(假设所有模块都包含一个公共类名)。

    编辑:解决方案:(感谢Coonj&Rick)这最终是有效的。还不知道为什么,但是 fromlist 必须是“任何明显的东西”,因为当我把字母“a”作为一个值时它起作用(奇怪的是,因为文件中只有一个类)。

    def get_struct_module(self, name):
        try:
            return = __import__("neoform.structures." + name, fromlist='*')
        except ImportError, e:
            self.out.add("Could not load struct: neoform.structure." + name + "\n\n" + "Error " + str(e.args))
    
    7 回复  |  直到 11 年前
        1
  •  10
  •   Rick Copeland    15 年前

    我不知道“失败”是什么意思,所以我只想提一下 __import__('structures.index') 实际上,应该可以工作,但它没有在当前作用域中分配模块名称。为此(然后使用动态导入模块中的类),必须使用:

    structures = __import__('structures.index')
    structures.index.SomeClass(...)
    

    有关的完整详细信息 __import__ 是可用的 here .

    编辑:(基于问题编辑)

    进口 neoform.structures.index ,并返回 index 模块,您将执行以下操作:

    structures = __import__('neoform.structures.index', 
                            fromlist=['does not in fact matter what goes here!'])
    

    因此,如果您有一个包名称列表 packages ,您可以导入 指数 模块并实例化一些 MyClass 使用以下代码为每个类初始化:

    modules = [ __import__('neoform.%s.index' % pkg, fromlist=['a']) 
                for pkg in packages ]
    objects = [ m.MyClass() for m in modules ]
    
        2
  •  4
  •   Jason Coon    15 年前

    要导入子模块,需要在 fromlist 精氨酸 __import__()
    例如,相当于:

    import structures.index
    

    是:

    structures = __import__('structures', fromlist=['index'])
    

    在地图上做这件事有点棘手…

    import mod1.index
    import mod2.index
    import mod3.index
    

    对于这些导入,您需要定义一个新函数来获取 index 每个模块的子模块:

    def getIndexMods(mod_names):
      mod_list = map(lambda x: __import__(x, fromlist='index'))
      index_mods = [mod.index for mod in mod_list]
      return index_mods
    

    现在,您可以这样做来获取对所有索引模块的引用:

    index_mods = getIndexMods(['mod1', 'mod2', 'mod3'])
    

    此外,如果要获取未命名为“index”的子模块,则可以执行以下操作:

    mod1, mod2, mod3 = map(lambda x,y: __import__(x, fromlist=y), 
      ['mod1', 'mod2', 'mod3'], ['index1', 'index2', 'index3'])
    
        3
  •  3
  •   FogleBird    15 年前

    对这个助手方法使用全范围(“neoform.structures.index”)。

    def import_module(name):
        mod = __import__(name)
        components = name.split('.')
        for comp in components[1:]:
            mod = getattr(mod, comp)
        return mod
    
    module = import_module("neoform.structures.index")
    # do stuff with module
    
        4
  •  1
  •   dfa    15 年前

    这里是Java程序员,但我认为你需要 imp module

        5
  •  1
  •   rorycl    14 年前
    >>> import imp
    >>> fm = imp.find_module('index', ['./structures']) # for submodule
    >>> mymod = imp.load_module('structures.index', *fm)
    >>> mymod
    <module 'structures.index' from './structures/index.pyc'>
    >>> x = mymod.insideIndex()
    Initialising index class...
    

    哇!

        6
  •  0
  •   S.Lott    15 年前

    你到底为什么要换

    import structures.index
    

    具有

    map(__import__, ["structures.index"])
    

    第一个(a)工作,(b) 直接支持动态和(c)。有什么可能的用例可以用更复杂的东西替换易于更改的纯文本源?

    简而言之:不要这样做。它没有任何价值。


    编辑

    “我正在从数据库中获取导入”是一项高尚的努力,但仍然不明智。什么代码块依赖于这些导入?整个代码块——导入和全部——就是您想要执行的。整个代码块——导入、语句和所有东西——应该是一个普通的、旧的Python模块文件。

    从文件系统导入该代码块。使用数据库来标识哪个文件,文件的作者——任何您想使用数据库的东西。但只需以最简单的方式导入和执行模块。

        7
  •  0
  •   jdsantiagojr    11 年前

    真是迟到了。但我在谷歌上搜索这个问题。我做了一些尝试和错误。不确定这段代码是否有用,但这里是。用于烧瓶部位。

    modules = ['frontend', 'admin']
    for module in modules:
        mod = __init__('controllers.%s' % module, fromlist=[module])
        app.register_blueprint(mod.blueprint_mod)
    
    
    # or
    from importlib import import_module
    modules = ['frontend', 'admin']
    for module in modules:
        mod = import_module('controllers.%s' % module)
        app.regitster_blueprint(mod.blueprint_mod)