如何通过clipspy将I/O同时路由到控制台与日志文件?
问题
我在Ubuntu 22.04 LTS系统中使用clipspy v1.0.0与Python 3.10。希望CLIPS规则中的printout语句(如(printout t 'WARN: Listen up, maggots...'))调用自定义函数输出到控制台,同时解析消息识别日志级别,用logging模块写入对应级别的日志文件。目前遇到两个问题:
- 日志文件已创建但无内容写入;
- stdout直接路由到Python的stdout,未调用自定义函数。
请问如何修改代码,实现CLIPS程序中(printout t)语句同时输出到控制台,并按指定日志级别写入日志文件?
解决方案
核心思路
要拦截CLIPS的printout输出,需替换CLIPS的标准输出回调,将printout t的内容定向到自定义处理函数,在函数内完成控制台输出与日志文件写入的逻辑。
完整代码示例
Python代码
import logging from clips import Environment # 配置logging模块:同时输出到控制台和日志文件 logging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('clips_logs.log'), logging.StreamHandler() ] ) # 自定义CLIPS输出处理函数 def clips_output_processor(message: str): # 清理消息格式:去除首尾引号、换行符 cleaned_msg = message.strip().strip("'\"") if not cleaned_msg: return # 定义日志级别前缀映射 level_map = { 'DEBUG:': logging.DEBUG, 'INFO:': logging.INFO, 'WARN:': logging.WARNING, 'ERROR:': logging.ERROR, 'CRITICAL:': logging.CRITICAL } # 匹配级别前缀并写入对应日志 for prefix, level in level_map.items(): if cleaned_msg.startswith(prefix): log_content = cleaned_msg[len(prefix):].strip() logging.log(level, log_content) return # 无匹配级别时默认按INFO输出 logging.info(cleaned_msg) def main(): env = Environment() # 替换CLIPS的标准输出回调,绑定到自定义处理函数 env.define_function(clips_output_processor, name='stdout-write') # 加载CLIPS规则文件 env.load('rules.clp') # 启动CLIPS推理 env.reset() env.run() if __name__ == '__main__': main()
CLIPS规则文件(rules.clp)
(defrule test-log-outputs => (printout t 'DEBUG: System initialization complete' crlf) (printout t 'INFO: User login successful' crlf) (printout t 'WARN: Disk space is low' crlf) (printout t 'ERROR: Database connection failed' crlf) (printout t 'Plain message without level tag' crlf) )
关键修改说明
- 替换CLIPS标准输出:通过
env.define_function(..., name='stdout-write'),将CLIPS中printout t的输出目标绑定到自定义函数,替代默认的stdout路由。 - 完善日志配置:同时添加
FileHandler和StreamHandler,确保日志既写入文件又输出到控制台,格式包含时间戳、级别和消息内容。 - 消息解析逻辑:在处理函数中识别消息开头的级别前缀,将内容路由到对应级别的日志,无匹配前缀的内容默认按INFO级别处理。
验证效果
运行Python程序后:
- 控制台会实时输出所有CLIPS的
printout内容; clips_logs.log文件中会按日志级别记录消息,每条日志包含时间戳、级别标签和清理后的内容。
内容的提问来源于stack exchange,提问作者Homunculus Reticulli
相关产品推荐
相关产品推荐

