递归地导入所有接口实现并在Python3中实例化它们

递归地导入所有接口实现并在Python3中实例化它们,python,python-3.x,Python,Python 3.x,我正在构建一个脚本运行程序,因此可以很容易地重用脚本代码,但我想让人们可以轻松地添加更多脚本,而无需更改runscript.py方法。理想情况下,我希望能够调用run-scripts.py,并让它在类中执行接口。现在我正在测试导入功能,因此如果我运行run-script.py list,它将列出基类接口的所有实现并在其上运行函数 我的文件夹布局如下所示: run-script.py |- a |- script-a.py |- script-ab.py |- b |- scri

我正在构建一个脚本运行程序,因此可以很容易地重用脚本代码,但我想让人们可以轻松地添加更多脚本,而无需更改
runscript.py
方法。理想情况下,我希望能够调用
run-scripts.py
,并让它在类中执行接口。现在我正在测试导入功能,因此如果我运行
run-script.py list
,它将列出基类接口的所有实现并在其上运行函数

我的文件夹布局如下所示:

run-script.py
|- a
   |- script-a.py
   |- script-ab.py
|- b
   |- script-b.py
   |- ...
|- ...
我利用一个抽象基类来定义接口契约,如下所示:

run-script.py
|- a
   |- script-a.py
   |- script-ab.py
|- b
   |- script-b.py
   |- ...
|- ...
class ScriptRunnerBaseClass(元类=ABCMeta):
@抽象方法
def运行(自):
通过
@抽象方法
def说明(自我):
通过
然后执行如下实现:

run-script.py
|- a
   |- script-a.py
   |- script-ab.py
|- b
   |- script-b.py
   |- ...
|- ...
class AppStats(ScriptRunnerBaseClass,元类=ABCMeta):
定义初始化(自):
通过
def说明(自我):
return“这是我的描述!”
def运行(自):
self.做事
在我的
runscript.py
entrypoint中,我目前正试图列出抽象基类的所有实现的描述实现。我找到了一个,这就是我目前所拥有的

import argparse
导入gc
导入导入库
进口检验
进口蛋白胶
导入系统
从检查导入类
从pathlib导入路径
从cloudfoundry.runner导入ScriptRunnerBaseClass
类ScriptLoader(对象):
忽略的位置=[“venv”]
定义初始化(自):
通过
@静力学方法
def load_all():
对于pkgutil.iter_模块([Path(_文件__).parent])中的(u,name,u):
imported_module=importlib.import_module(名称,包=_名称)
对于i in dir(导入的_模块):
attribute=getattr(导入的_模块,i)
如果inspect.isclass(属性)和IsubClass(属性,ScriptRunnerBaseClass):
setattr(sys.modules[\u__;name],name,attribute)
def main():
parser=argparse.ArgumentParser(description=“针对Cloud Foundry运行脚本!”)
parser.add_参数(“list”,help=“列出所有可用的cf脚本”)
args=parser.parse_args()
ScriptLoader.load_all()
如果args.list:
打印脚本()
def print_脚本():
对于gc.get_objects()中的obj:
如果是isclass(obj):
如果issubclass(ScriptRunnerBaseClass,obj):
#以下是我的描述!
打印(“{0}:{1}.”格式(obj.\uuuu name\uuuu,obj().description())
如果名称=“\uuuuu main\uuuuuuuu”:
main()
我已经验证了模块是通过REPL加载的,因此我知道
ScriptLoader.load_all()
功能正在执行我希望它执行的操作。当我运行它时,我得到一个
TypeError
我不能100%确定我是否理解:

✗ python3 run-script.py列表
回溯(最近一次呼叫最后一次):
文件“run script.py”,第50行,在
main()
文件“runscript.py”,第39行,在main中
打印脚本()
打印脚本中第46行的文件“run script.py”
打印(“{0}:{1}.”格式(obj.\uuuu name\uuuu,obj().description())
TypeError:无法使用抽象方法\uuuHash实例化可哈希的抽象类__

我做错了什么?我如何才能达到加载所有接口实现并对其调用方法的预期结果?

您真的打算测试
issubclass(ScriptRunnerBaseClass,obj)
,而不是
issubclass(obj,ScriptRunnerBaseClass)
?您的测试将为您提供
ScriptRunnerBaseClass
的(抽象)基类,而不是(抽象)子类。值得注意的是,
ScriptRunnerBaseClass
满足了许多纯粹的抽象类,比如
Hashable
。哦,我完全不是有意这么做的。我应该编辑我的问题还是保留它?如果这是无意的,它很可能是您错误的来源。嗯,我修复了它,它给了我一个不同的错误,所以我想我会继续调试它,看看我发现了什么。不过,感谢@Mistermiagi指出这一点。:)您真的打算测试
issubclass(ScriptRunnerBaseClass,obj)
,而不是
issubclass(obj,ScriptRunnerBaseClass)
?您的测试将为您提供
ScriptRunnerBaseClass
的(抽象)基类,而不是(抽象)子类。值得注意的是,
ScriptRunnerBaseClass
满足了许多纯粹的抽象类,比如
Hashable
。哦,我完全不是有意这么做的。我应该编辑我的问题还是保留它?如果这是无意的,它很可能是您错误的来源。嗯,我修复了它,它给了我一个不同的错误,所以我想我会继续调试它,看看我发现了什么。不过,感谢@Mistermiagi指出这一点。:)