动态加载Python模块
我正在尝试动态加载我创建的模块。
现在这样做是可以的:
import structures.index
但是如果我尝试通过动态导入来做同样的事情,就会失败。
struct = __import__("structures.index")
出现的错误是:
Error ('No module named structures.index',)
有人知道为什么吗?
编辑:当使用完整作用域时(这似乎有点有效):
struct = __import__("neoform.structures.index")
这没有抛出任何错误,但它没有加载索引模块,而是加载了“neoform”模块。
“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 个回答
使用完整的范围("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
要导入子模块,你需要在 __import__()
的 fromlist
参数中指定它们。
比如,下面这段代码的意思是:
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 模块的引用:
index_mods = getIndexMods(['mod1', 'mod2', 'mod3'])
另外,如果你想获取一些不是叫 'index' 的子模块,你可以这样做:
mod1, mod2, mod3 = map(lambda x,y: __import__(x, fromlist=y),
['mod1', 'mod2', 'mod3'], ['index1', 'index2', 'index3'])
我不太明白“它失败了”是什么意思,所以我只想提一下,__import__('structures.index')
其实是可以工作的,但它不会把模块名放在当前的作用域里。要做到这一点(然后使用动态导入的模块中的一个类),你需要这样做:
structures = __import__('structures.index')
structures.index.SomeClass(...)
关于 __import__
的详细信息可以在 这里 找到。
编辑:(基于问题的修改)
要导入 neoform.structures.index
并返回 index
模块,你可以这样做:
structures = __import__('neoform.structures.index',
fromlist=['does not in fact matter what goes here!'])
所以如果你有一个包名的列表 packages
,你可以导入它们的 index
模块,并为每个模块实例化一个 MyClass
类,使用以下代码:
modules = [ __import__('neoform.%s.index' % pkg, fromlist=['a'])
for pkg in packages ]
objects = [ m.MyClass() for m in modules ]