我目前正在编写某种小型 API 来支持扩展模块类。用户应该能够在配置中写入他们的类名,然后在我们的程序中使用它。契约(Contract)是,类的模块有一个名为 create(**kwargs)
的函数来返回我们的基本模块类的实例,并放置在一个特殊的文件夹中。但是一旦动态导入,isinstance 检查就会失败。
模块放置在 lib/services/name
模块基类(在 lib/services/service 中)
class Service:
def __init__(self, **kwargs):
#some initialization
示例模块类(在 lib/services/ping 中)
class PingService(Service):
def __init__(self, **kwargs):
Service.__init__(self,**kwargs)
# uninteresting init
def create(kwargs):
return PingService(**kwargs)
导入函数
import sys
from lib.services.service import Service
def doimport( clazz, modPart, kw, class_check):
path = "lib/" + modPart
sys.path.append(path)
mod = __import__(clazz)
item = mod.create(kw)
if class_check(item):
print "im happy"
return item
调用代码
class_check = lambda service: isinstance(service, Service)
s = doimport("ping", "services", {},class_check)
print s
from lib.services.ping import create
pingService = create({})
if isinstance(pingService, Service):
print "why this?"
我到底做错了什么
这是一个压缩的小示例,只需解压并运行 test.py
(不带参数)
zip example
最佳答案
问题出在您的 ping.py
文件中。我不知道确切的原因,但是当动态导入时,它不接受 from service import Service
行,因此您只需将其更改为相对路径:from lib.services。服务导入服务
。将 lib/services
添加到 sys.path
无法使其继承,我觉得很奇怪......
另外,我正在使用 imp.load_source
,它看起来更强大:
import os, imp
def doimport( clazz, modPart, kw, class_check):
path = os.path.join('lib', modPart, clazz + '.py')
mod = imp.load_source( clazz, path )
item = mod.create(kw)
if class_check(item):
print "im happy"
return item
关于python 2.7 isinstance 在动态导入的模块类中失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17179440/