- 如何在 command1.py 文件中导入 ICommand 进行继承?
您的项目必须在适当的包中。如果你还没有这样做,你应该这样做。
一旦 Python 了解“command1”在包中,您就可以在包中执行以下操作:
from ..ICommand import ICommand
(当然,ICommand 必须是定义您的 ICommand 的 .py 文件)。
- 如何为 .py 文件中包含的每个类创建一个实例
在命令文件夹中?
对于 Python,除非您显式导入文件,否则 .py 文件与目录中的任何数据文件一样好。该语言允许但不会对插件下的任何文件执行任何“自动发现”。
你可以自己做,你可以使用一个框架来做这种事情 - zope.configuration 是一个,但你必须使用它应该扫描的文件夹创建类似 xml 的文件。
自己做很容易,只需列出所需的文件夹,然后为其中的任何 Python 文件调用 __import__。
调用__import__ 返回的对象是模块本身,然后您可以检查其内容以查找ICommand 的子类(或其他实现),然后实例化。
module = __import__(...)
plugins = {}
for name, obj in module.__dict__.items():
if isinstance(obj, ICommand):
plugins[name] = obj() # This instatiate the class
我有两个答案以及如何做到这一点的明确示例:
Load module to invoke its decorators
Python: import every module from a folder?
- 有什么办法可以保证插件文件只包含一个
派生 ICommand 类的定义?
是的。
但你不应该像你所说的那样把这个限制放在那里。
上面用于获取 ICommand 子类的 sn-p 检查所有模块的顶级内容,您可以轻松地在任何不是 ICommand 子类的变量、函数或类上引发异常。
然而,这不是一个合理的限制:在 Python 中,通常需要与类无关的小型“实用”函数,或其他将保持常量值的变量——将它们限制为插件的类成员是没有用的 -在。同样,如果您担心插件包含不应该存在的任意代码:您根本无法阻止这种情况。在 Python 进程中安全地“沙箱化”Python 文件是不可行的。多年来,非常优秀的人试图拥有一个“Python 沙箱”,但结果很沮丧。 (如果这是要求,请使用操作系统级别的进程资源限制,并运行您的插件,即仅在具有这些限制的进程中导入它们的文件)
否则,您可能的意思是您想要“每个文件的 ICommand 的单个子类”,没有其他限制:然后只需在上述循环中插入一个检查以实例化插件 - 如果它在同一个文件,引发异常。