如何使用clipspy提取CLIPS规则文件中的printout内容用于GUI开发
基于clipspy捕获printout输出并实现GUI交互的解决方案
核心原理
CLIPS中(printout t ...)的t参数代表标准输出路由,默认绑定Python的stdout;而read函数默认绑定Python的stdin输入。我们只需要自定义这两个逻辑的处理函数,就能实现将规则输出导到GUI窗口、从GUI弹窗获取用户输入的交互逻辑。
方法1:简单捕获所有printout输出(无GUI场景)
如果只需要一次性提取所有规则运行过程中的printout内容,不需要实时交互,直接重定向标准输出即可:
import clips from io import StringIO from contextlib import redirect_stdout env = clips.Environment() env.load('rule_file.CLP') # 初始输入 print("需要什么类型的服务?('BR' 代表租车/还车 / 'EM' 代表紧急服务)") user_input = input() env.assert_string(f"(service {user_input})") # 捕获运行阶段所有输出 output_buffer = StringIO() with redirect_stdout(output_buffer): env.run() clips_output = output_buffer.getvalue() print("提取到的CLIPS打印内容:\n", clips_output)
方法2:适配GUI的实时交互方案(推荐)
如果要做弹窗交互的GUI,需要自定义CLIPS的输出路由和输入函数,以下是基于tkinter的完整可运行示例:
import clips import tkinter as tk from tkinter import simpledialog, messagebox # 初始化tkinter,隐藏主窗口只保留弹窗 root = tk.Tk() root.withdraw() env = clips.Environment() # 自定义输出处理:捕获printout内容弹提示框 def capture_printout(message): msg = message.strip() if msg: messagebox.showinfo("系统提示", msg) return True # 注册自定义路由,优先级高于默认标准输出路由 env.add_router( name="gui_output", priority=100, query=lambda _: True, print=capture_printout ) # 自定义输入函数:替换CLIPS默认的read,从弹窗获取输入 def gui_read(): input_val = simpledialog.askstring("请输入", "请输入你的答案:") return input_val.strip() if input_val else "" # 注册到CLIPS环境,覆盖原生read函数 env.define_function(gui_read, name="read") # 加载规则文件 env.load("rule_file.CLP") # 初始服务选择提问 service = simpledialog.askstring("服务选择", "需要什么类型的服务?\n输入BR: 租车/还车 输入EM: 紧急服务") if service: env.assert_string(f"(service {service.strip().upper()})") # 运行规则,自动触发弹窗提问、输入收集的完整流程 env.run() messagebox.showinfo("运行完成", "专家系统已执行完毕!")
注意事项
- 自定义路由的优先级设置为100即可覆盖CLIPS默认的标准输出路由,所有
(printout t ...)的内容都会优先传给你定义的打印函数 - 原生规则里的
upcase(read)逻辑可以保留,也可以直接在Python的自定义read函数里处理完大小写再返回 - 如果你用其他GUI框架(PyQt/PySide等),只需要替换示例里的tkinter弹窗逻辑即可,clipspy的路由和自定义函数注册逻辑通用
内容的提问来源于stack exchange,提问作者Yew
相关产品推荐
相关产品推荐

