设计python插件系统

时间:2016-02-20 20:49:17

标签: python plugins

我目前正在开发一个处理metrics的用户指定列表(在文件中)的系统;度量是一些字符串的集合,以及关于如何执行某个计算的一些逻辑。定期在Linux服务器上运行python脚本并查询该文件。

度量标准应该易于扩展,因此我正在寻找一些模块化方法来将计算代码封装到度量标准的规范中。除了创建一个配置解析系统,这将严重限制计算的复杂性,我正在寻找一个插件系统,其中每个指标的计算可以在python代码中指定。

例如,以下是指标的核心单位。

db = "database0"
mes = "measurement0"
tags = ["alpha", "beta", "delta"]
calculation: (accepts parameters a and b)
    for item in a:
        b.add(a)
    return b

python脚本需要从文件中获取每个指标,访问其字符串字段并执行其计算代码,并将相同的参数传递给每个指标。

我目前有一种糟糕的方法;在一个单独的python文件中,我定义了一个基类,该基类将由每个新指标进行扩展。这就是它的样子

class Metric(object):
    def __init__(self, database_name, measurement_name, classad_tags, classad_fields=[]):
        """
        A specification of a metric.
        Arguments:
            database_name    - name of the influx DB (created if doesn't exist)
            measurement_name - measurement name with which to label metric in DB
            classad_tags     - list of classad fields (or mock ads) which will
                               segregate values at a time for this metric, becoming
                               tags in the influxDB measurement
            classad_fields   - any additional job classad fields that this metric will
                               look at (e.g. for metric value calculation).
                               These must be declared so that the daemon can fetch any
                               needed classads from condor
        """
        self.db = database_name
        self.mes = measurement_name
        self.tags = classad_tags
        self.fields = classad_fields

    def calculate_at_bin(self, time_bin, jobs):
        """
        """

        raise ReferenceError("")


"""
--------------------------------------------------------------------------------------
"""


class metric0(Metric):
    def __init__(self):

        db = 'testdb'
        mes = 'testmes0'
        tags = ['Owner']
        fields = []
        super(metric0, self).__init__(db, mes, tags, fields)

    def calculate_at_bin(self, time_bin, jobs):

        for job in jobs:
            if job.is_idle_during(time_bin.start_time, time_bin.end_time):
                time_bin.add_to_sum(1, job.get_values(self.tags))
        return time_bin.get_sum()

要创建新指标,您需要创建一个新的Metric子类,将字符串字段传递给超级构造函数并覆盖calculate_at_bin方法。在主python脚本中,我使用类似......

之类的东西创建每个度量的实例
metrics = [metric() for metric in vars()['Metric'].__subclasses__()]

然而,这显然是可怕的。 它涉及完全任意但必需的唯一子类名称(metric0)和与度量不相关的代码(例如类定义,调用构造函数等)。

我可以想象另一个可怕的方法,比如一个配置文件,其中包含一些eval'的代码,但我也想避免这样做。

请注意,不担心安全性或代码注入;这个系统真的只会被我能亲自指导的少数人使用。 所以;我应该怎么做呢?

1 个答案:

答案 0 :(得分:0)

您是否考虑过将度量标准的代码作为可导入模块,提供{{1}}函数作为"接口",将所有此类模块放在目录中,然后动态导入它们?将删除可能的名称冲突的问题,如果安全性无关紧要,它将至少非常简单地处理......