如果我使用相应目录module/
定义模块模块,我可以动态加载来自a.py
或b.py
等子模块的类吗?
- 模块
----a.py
----b.py
这是否需要知道要搜索的班级名称?我可以设置一个基类,以某种方式加载这些孩子?
基本用例是允许用户编写程序将加载的自己的代码。与rails允许您在某些目录中编写自己的控制器,视图和模型的方式相同。
我到目前为止动态加载模块的代码是
def load(folder):
files = {}
for filename in os.listdir(folder):
if (filename[0] != '_' and filename[0] != '.'):
files[filename.rstrip('.pyc')] = None
# Append each module to the return list of modules
modules = []
mod = __import__(folder, fromlist=files.keys())
for key in files.keys():
modules.append(getattr(mod, key))
return modules
我希望修改它以返回类对象。
答案 0 :(得分:2)
您正在寻找pkgutil.walk_packages
。使用此功能,您可以执行以下操作:
def load(root_import_path, is_valid=lambda entity: True):
"""Returns modules in ``root_import_path`` that satisfy the ``is_valid`` test
:param root_import_path: An string name for importing (i.e. "myapp").
:param is_valid: A callable that takes a variable and returns ``True``
if it is of interest to us."""
prefix = root_import_path + u"."
modules = []
for _, name, is_pkg in walk_packages(root_import_path, prefix=prefix):
if is_pkg:
continue
module_code = __import__(name)
contents = dir(module_code)
for thing in contents:
if is_valid(thing):
modules.append(thing)
return modules
另外,如果你不介意接受依赖,你可以试试straight.plugin
加载器,这比这个简单的load
函数复杂一点。
答案 1 :(得分:2)
#!/usr/bin/env python
import os
import sys
import inspect
def load_modules_from_path(path):
"""
Import all modules from the given directory
"""
# Check and fix the path
if path[-1:] != '/':
path += '/'
# Get a list of files in the directory, if the directory exists
if not os.path.exists(path):
raise OSError("Directory does not exist: %s" % path)
# Add path to the system path
sys.path.append(path)
# Load all the files in path
for f in os.listdir(path):
# Ignore anything that isn't a .py file
if len(f) > 3 and f[-3:] == '.py':
modname = f[:-3]
# Import the module
__import__(modname, globals(), locals(), ['*'])
def load_class_from_name(fqcn):
# Break apart fqcn to get module and classname
paths = fqcn.split('.')
modulename = '.'.join(paths[:-1])
classname = paths[-1]
# Import the module
__import__(modulename, globals(), locals(), ['*'])
# Get the class
cls = getattr(sys.modules[modulename], classname)
# Check cls
if not inspect.isclass(cls):
raise TypeError("%s is not a class" % fqcn)
# Return class
return cls
def main():
load_modules_from_path('modules')
# load the TestClass1
class_name = load_class_from_name('class1.TestClass1')
# instantiate the Testclass1
obj = class_name()
# using this object obj to call the attributes inside the class
print obj.testclass1()
if __name__ == '__main__': main()
在模块目录内,还有另外两个用于测试的模块:
[♫ test] modules :~ pwd
/tmp/dynamic_loader/modules
[♫ test] modules :~ ls -lR
total 32
-rw-r--r-- 1 staff staff 138 Aug 30 21:10 class1.py
-rw-r--r-- 1 staff staff 575 Aug 30 21:11 class1.pyc
-rw-r--r-- 1 staff staff 139 Aug 30 21:11 class2.py
-rw-r--r-- 1 staff staff 576 Aug 30 21:11 class2.pyc
[♫ test] modules cat class1.py
class TestClass1(object):
def testclass1(self):
print 'I am from testclass1'
def some_function():
print 'some function 1'
答案 2 :(得分:0)
以下两个模块一起工作,做了类似的事情。基本上,您可以dir()
模块并检查使用getattr
检索的类的类类型。
http://code.google.com/p/pycopia/source/browse/trunk/QA/pycopia/QA/shellinterface.py
http://code.google.com/p/pycopia/source/browse/trunk/aid/pycopia/module.py