在 Python 中实现“规则引擎”
Posted
技术标签:
【中文标题】在 Python 中实现“规则引擎”【英文标题】:Implementing a "rules engine" in Python 【发布时间】:2010-10-02 20:04:32 【问题描述】:我正在用 Python 编写一个日志收集/分析应用程序,我需要编写一个“规则引擎”来匹配和处理日志消息。
它需要具有:
消息本身的正则表达式匹配 消息严重性/优先级的算术比较 布尔运算符我设想一个示例规则可能是这样的:
(message ~ "program\\[\d+\\]: message" and severity >= high) or (severity >= critical)
我正在考虑使用PyParsing 或类似方法来实际解析规则并构造解析树。
我想到的当前(尚未实现)设计是为每种规则类型设置类,并根据解析树构造并将它们链接在一起。然后每个规则都会有一个“matches”方法,无论它是否匹配规则,它都可以返回一个消息对象。
很快,例如:
class RegexRule(Rule):
def __init__(self, regex):
self.regex = regex
def match(self, message):
return self.regex.match(message.contents)
class SeverityRule(Rule):
def __init__(self, operator, severity):
self.operator = operator
def match(self, message):
if operator == ">=":
return message.severity >= severity
# more conditions here...
class BooleanAndRule(Rule):
def __init__(self, rule1, rule2):
self.rule1 = rule1
self.rule2 = rule2
def match(self, message):
return self.rule1.match(message) and self.rule2.match(message)
然后这些规则类将根据消息的解析树链接在一起,并在顶部规则上调用 match() 方法,该方法将向下级联,直到所有规则都被评估。
我只是想知道这是否是一种合理的方法,或者我的设计和想法是否完全不合时宜?不幸的是,我从来没有机会在大学学习编译器设计课程或类似的课程,所以我几乎是自己想出了这些东西。
能否请在这类事情上有一定经验的人加入并评估这个想法?
编辑: 到目前为止,一些很好的答案,这里有一点澄清。
该程序的目的是从网络上的服务器收集日志消息并将它们存储在数据库中。除了收集日志消息之外,收集器还将定义一组规则,这些规则将根据条件匹配或忽略消息,并在必要时标记警报。
我看不到规则的复杂性超过中等,它们将被应用在一个链(列表)中,直到匹配的警报或忽略规则被命中。但是,这部分与问题不太相关。
就语法接近 Python 语法而言,是的,这是真的,但是我认为很难将 Python 过滤到用户不会无意中使用不符合规则的规则做一些疯狂的事情有意的。
【问题讨论】:
你完成过这个项目吗?仅供参考,我曾经使用过一个类似的商业产品,它的作用几乎与你试图做的一样。它侦听包含警报的 SNMP 消息,并将它们标准化为警报数据库。标准化是用 Perl 之类的语言完成的,由通用解析库和针对每种日志类型的大量自定义代码组成。所以最终,“规则引擎”就是类似于 Perl 的语言。 【参考方案1】:不要再发明另一种规则语言。
要么使用 Python,要么使用其他现有的、已经调试过的工作语言,例如 BPEL。
只需在 Python 中编写您的规则,导入它们并执行它们。生活更简单,更容易调试,而且您实际上已经解决了实际的日志读取问题,而不会产生另一个问题。
想象一下这个场景。你的程序中断了。现在是规则解析、规则执行或规则本身。您必须调试所有三个。如果你用 Python 编写规则,那就是规则,就是这样。
“我认为很难将 Python 过滤到用户不会无意中使用非预期规则做一些疯狂的事情的程度。”
这主要是“我想编写一个编译器”的论点。
1) 您是主要用户。您将编写、调试和维护规则。真的有一群疯狂的程序员会做疯狂的事情吗?真的吗?如果有任何潜在的疯狂用户,与他们交谈。教他们。不要通过发明一种新语言来对抗它们(然后你必须永远维护和调试它。)
2) 这只是日志处理。 疯狂并没有真正的成本。没有人会用错误的日志处理来颠覆世界经济体系。不要将几十行 Python 的小任务放到一个 1000 行的解释器上来解释一些规则语言的几十行。只需编写几十行 Python。
只需尽可能快速清晰地用 Python 编写它,然后继续下一个项目。
【讨论】:
我知道这已经有一段时间了,但在我被说服之前,我不得不考虑这个解决方案相当长的一段时间。但是,在阅读了您最近引用此问题的博客文章并使用 Zenoss 后,它完全符合您的建议,我不得不说我被卖掉了。 +1 -- 特定领域的语言往往看起来像没有括号的 Python(即 twill.idyll.org )。【参考方案2】:您可能还想查看PyKE。
【讨论】:
“谁拥有斑马?”除了示例性 Python 'constraint' 示例之外,问题现在还包括 PyKE 中的一个解决方案 -- ***.com/questions/318888/…【参考方案3】:在不知道应用程序范围的情况下回答这个问题有点困难。
你想推理什么? 您指的是什么级别的分析? 您认为这些规则变得多么复杂? 不同规则之间的相互作用有多复杂?在频谱的一端是一种简单的一次性方法,就像您提出的那样。如果规则很少,相对简单,并且您没有做任何比聚合与指定规则匹配的日志消息更复杂的事情,这很好。
另一方面是一个重量级的推理系统,比如CLIPS,它有一个Python interface。这是一个具有推理功能的真正规则引擎,并提供进行复杂推理的能力。如果您正在构建类似诊断引擎的东西,它会根据程序日志运行,这可能更合适。
编辑:
我会说当前的实施理念很适合您正在做的事情。还有更多,我认为您可能会冒过度设计解决方案的风险。它似乎捕获了您想要的内容,仅根据几个不同的标准匹配日志消息。
【讨论】:
【参考方案4】:与 Python 语法本身不同的唯一地方是 message ~ "program\\[\d+\\]: message"
部分,所以我想知道您是否真的需要新语法。
更新:好的,您有可用性或安全性方面的顾虑——这是合理的。几个建议:
从 Awk 中获取提示并简化模式匹配语法,例如/program\[\d+\]: message/
而不是 message ~ "program\\[\d+\\]: message"
。
我会通过在解析输入时转换为 Python 表达式来实现它,而不是构建一个对象树来评估,除非您希望对这些事情执行比评估更多的操作。这应该需要更少的代码并且运行得更快。顶层可能类似于:
def compile(input):
return eval('lambda message, severity: %s' % parse(input))
另一个想法,更远的地方:用 Lua 编写你的应用程序。它是为非程序员设计的,可以在不需要学习很多东西的情况下合理安全地扩展程序。 (有人告诉我,这种方式已成功使用,您可以沙箱评估,因此用户的代码无法获得您未明确传递给它的任何功能。)
我现在就闭嘴。 :-) 祝你好运!
【讨论】:
【参考方案5】:您可能还想看看pyDMNrules。它根据决策模型表示法 (DMN) 规则表构建规则引擎。
【讨论】:
以上是关于在 Python 中实现“规则引擎”的主要内容,如果未能解决你的问题,请参考以下文章