From be0ba3a3d6e435a4d34d92230faa0a006b5c0a15 Mon Sep 17 00:00:00 2001 From: flt6 <1404262047@qq.com> Date: Mon, 26 May 2025 23:26:31 +0800 Subject: [PATCH] use logging instead print Former-commit-id: bff176e0e99d1c50f48a63a3fd30adcee67777a8 --- .gitignore | 4 +- main.py | 106 ++++++++++++++++++++++++++++-------------------- test_logging.py | 35 ++++++++++++++++ utils.py | 57 ++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 46 deletions(-) create mode 100644 test_logging.py create mode 100644 utils.py diff --git a/.gitignore b/.gitignore index 44493e4..ff756d2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ - __pycache__ .idea data @@ -6,4 +5,5 @@ Imgs 0518 Input *.jpg -*.png \ No newline at end of file +*.png +logs \ No newline at end of file diff --git a/main.py b/main.py index 8f18020..a43d59e 100644 --- a/main.py +++ b/main.py @@ -4,36 +4,41 @@ from datetime import datetime import numpy as np import ch340 import atexit +import utils class MAT: def __init__(self, videoSourceIndex=0, bounce_time=1): - print('Initializing MAT...') + # 初始化logging + utils.setup_logging() + self.system_logger = utils.get_system_logger() + self.control_logger = utils.get_control_logger() + self.endpoint_logger = utils.get_endpoint_logger() + self.volume_logger = utils.get_volume_logger() + + self.system_logger.info('正在初始化MAT系统...') self.videoSourceIndex = videoSourceIndex self.cap = cv2.VideoCapture(videoSourceIndex, cv2.CAP_DSHOW) self.ch340 = ch340.CH340() self.bounce_time = bounce_time self.total_volume = 0 - self.start_time = time.time() - self.middle_time = time.time() - # 将开始时间转化为年月日时分秒的格式,后续文件命名都已此命名 - self.formatted_time = datetime.fromtimestamp(self.start_time).strftime('%Y%m%d_%H%M%S') - + self.start_time = 0 + self.middle_time = 0 + atexit.register(self.ch340.stop) - print("实验开始于", self.formatted_time) self.history = [] # 滑动窗口历史记录 self.colored_volume = None # 首次colored体积 self.colored_time = None # 首次colored时间 def ch340_pull(self): - print("开始抽取12ml") + self.control_logger.info("开始抽取12ml") self.ch340.max_speed() self.ch340.pull(vol=12) - print('完成抽取') + self.control_logger.info('完成抽取') def ch340_init(self): self.ch340.push(speed=1,t=1) self.ch340.pull(speed=1.2,vol=3) - print('CH340 INITED') + self.control_logger.info('已初始化') def ch340_push(self, speed=0.1): self.ch340.push_async(speed=speed, t=1) @@ -51,12 +56,11 @@ class MAT: """预测当前图像状态,返回'transport'、'middle'或'colored'""" suc, im = self.cap.read() if not suc: - print("Failed to capture frame from camera.") + self.control_logger.error("无法从摄像头捕获帧") return None ret,rate = self.predictor(im) if ret is None: - print("Fallback") return None now = time.time() @@ -69,7 +73,7 @@ class MAT: self.history.pop(0) if not self.history: - print("Warning: No history available.") + self.control_logger.error("未预期的没有可用的历史记录") return ret # 处理检测结果 @@ -79,25 +83,24 @@ class MAT: self.process_left(now) self.typ = 1 self.middle_time = now - print(f"检测到middle,切换到慢速模式,当前体积: {val}") + self.control_logger.info(f"检测到middle,切换到慢速模式,当前体积: {val:.2f} ml") elif ret == "colored": # 检测到colored时记录当前体积 if self.colored_volume is None: self.colored_volume = val self.colored_time = now - print(f"检测到colored,记录体积: {self.colored_volume}") - - # 检查是否要停止 - if now - self.colored_time > self.bounce_time: + self.endpoint_logger.info(f"检测到colored,记录体积: {self.colored_volume:.2f} ml") + # 检查是否要停止 + if self.colored_time is not None and now - self.colored_time > self.bounce_time: colored_count = sum(1 for _, state, _ in self.history if state == "colored") if colored_count / len(self.history) > 0.9: - print(f"确认终点,最终体积: {self.colored_volume:0.2f} ml") + self.endpoint_logger.info(f"确认终点,最终体积: {self.colored_volume:.2f} ml") self.running = False self.ch340.stop() return "colored" else: - print(f"colored比例小于90%,当前体积: {val}, {colored_count / len(self.history)}") + self.endpoint_logger.warning(f"colored比例小于90%,当前体积: {val:.2f} ml, 比例: {colored_count / len(self.history):.2%}") self.colored_volume = val self.colored_time = now else: # ret == "transport" @@ -111,13 +114,13 @@ class MAT: self.process_left(now) # TODO: 滑动到第一个middle状态 self.middle_time = 0 - print(f"非middle比例超过90%,切回快速模式,当前体积: {val}") + self.control_logger.info(f"非middle比例超过90%,切回快速模式,当前体积: {val:.2f} ml") - # 如果已记录colored但在bounce_time内colored比例小于90%,重置 - if self.colored_volume is not None and now - self.colored_time > self.bounce_time: + # 如果已记录colored但在bounce_time内colored比例小于90%,重置 + if self.colored_volume is not None and self.colored_time is not None and now - self.colored_time > self.bounce_time: colored_count = sum(1 for _, state, _ in self.history if state == "colored") if colored_count / len(self.history) < 0.9: - print(f"colored比例小于90%,重置colored记录") + self.endpoint_logger.warning(f"colored比例小于90%,重置colored记录") self.colored_volume = None flag = False for t, state,vol in self.history: @@ -125,13 +128,14 @@ class MAT: if not flag: flag = True continue - print(f"滑动窗口到: {vol} at {t}") + self.endpoint_logger.debug(f"滑动窗口到: {vol:.2f} ml at {t}") self.colored_volume = vol self.colored_time = t break else: - print("Warning: Unusual condition, colored for over 90%% but last is transport") - print(f"疑似滴定终点: {self.colored_volume}") + self.endpoint_logger.warning("异常情况,colored超过90%但最后状态是transport") + self.endpoint_logger.info(f"疑似滴定终点: {self.colored_volume:.2f} ml") + cv2.putText(im, f"State: {ret}, rate: {round(rate,2)}, Vol: {val:.2f} ml, typ: {'slow' if self.typ else 'fast'}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (10,215, 255) if self.typ else (255,255,255), 2) @@ -156,38 +160,52 @@ class MAT: def __del__(self): self.cap.release() cv2.destroyAllWindows() - print("Experiment finished.") def run(self,quick_speed = 0.2,slow_speed = 0.05): self.running = True self.typ = 0 self.last = 0 self.speeds = (quick_speed, slow_speed) + + # 记录实验开始 + experiment_params = { + "视频源索引 ": self.videoSourceIndex, + "防抖时间 ": self.bounce_time, + "快速模式速度": f"{quick_speed} ml/次", + "慢速模式速度": f"{slow_speed} ml/次" + } + self.system_logger.info("实验参数:") + for key, value in experiment_params.items(): + self.system_logger.info(f" {key}: {value}") + + speed = self.speeds[self.typ] + while self.running: if self.total_volume % 12 == 0: self.ch340_pull() # 抽取12ml time.sleep(0.01) if not self.ch340.running: - print(f"Current Total Volume: {self.total_volume:0.2f} ml") - if self.typ == 0: # 每次加0.2ml - speed = quick_speed - self.ch340_push(speed) - self.total_volume += speed - else: - speed = slow_speed - self.ch340_push(speed) # 每次加0.05ml - self.total_volume += speed + self.volume_logger.info(f"当前体积: {self.total_volume:.2f} ml, 加入速度: {speed:.2f} ml/次") + + speed = self.speeds[self.typ] + self.ch340_push(speed) + self.total_volume += speed if self._pred() is None: - print("Prediction failed, skipping frame.") + self.control_logger.error("预测失败,跳过当前帧") continue - - print('----->>Visual Endpoint<<-----') - print(f"Total Volume: {self.total_volume} ml") - print(f"End point volume: {self.colored_volume} ml") - print(f"Theorical fixed volume: {self.colored_volume} ml") + # 实验结束,记录结果 + experiment_results = { + "总体积 ": f"{self.total_volume:.2f} ml", + "终点体积": f"{self.colored_volume:.2f} ml", + "理论体积": f"{self.colored_volume:.2f} ml", + "实验时长": f"{time.time() - self.start_time:.2f} 秒" + } + self.system_logger.info("实验结果:") + for key, value in experiment_results.items(): + self.system_logger.info(f" {key}: {value}") if __name__ == "__main__": @@ -199,7 +217,7 @@ if __name__ == "__main__": mat.run( slow_speed = 0.05, - quick_speed = 0.15, + quick_speed = 0.15, ) diff --git a/test_logging.py b/test_logging.py new file mode 100644 index 0000000..209a826 --- /dev/null +++ b/test_logging.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +测试logging系统的功能 +""" + +import utils + +def test_logging(): + """测试logging系统""" + # 初始化logging + log_file = utils.setup_logging() + print(f"日志文件已创建: {log_file}") + + # 获取各个模块的logger + system_logger = utils.get_system_logger() + hardware_logger = utils.get_hardware_logger() + vision_logger = utils.get_vision_logger() + control_logger = utils.get_control_logger() + endpoint_logger = utils.get_endpoint_logger() + volume_logger = utils.get_volume_logger() + + # 测试各个模块的日志输出 + system_logger.info("系统初始化完成") + hardware_logger.info("硬件连接正常") + vision_logger.debug("图像处理开始") + control_logger.warning("控制逻辑警告") + endpoint_logger.error("终点检测错误") + volume_logger.info("体积计算: 10.5 ml") + + print("日志测试完成!请检查logs目录下的日志文件。") + +if __name__ == "__main__": + test_logging() diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..dc04cb5 --- /dev/null +++ b/utils.py @@ -0,0 +1,57 @@ +import logging +import os +from datetime import datetime + + +def setup_logging(log_level=logging.INFO, log_dir="logs"): + """ + 设置logging配置,创建不同模块的logger + + Args: + log_level: 日志级别,默认INFO + log_dir: 日志文件存储目录,默认"logs" + """ + # 创建日志目录 + if not os.path.exists(log_dir): + os.makedirs(log_dir) + + # 获取当前时间作为日志文件名 + timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') + log_file = os.path.join(log_dir, f"titration_{timestamp}.log") + + # 配置根logger + logging.basicConfig( + level=log_level, + format='%(asctime)s - %(name)8s - %(levelname)7s - %(message)s', + handlers=[ + logging.FileHandler(log_file, encoding='utf-8'), + logging.StreamHandler() # 同时输出到控制台 + ] + ) + + return log_file + + +def get_system_logger(): + """系统初始化和控制相关的logger""" + return logging.getLogger("System") + +def get_hardware_logger(): + """硬件控制相关的logger(CH340等)""" + return logging.getLogger("Hardware") + +def get_vision_logger(): + """图像处理和预测相关的logger""" + return logging.getLogger("Vision") + +def get_control_logger(): + """控制逻辑相关的logger""" + return logging.getLogger("Control") + +def get_endpoint_logger(): + """终点检测相关的logger""" + return logging.getLogger("Endpoint") + +def get_volume_logger(): + """体积计算相关的logger""" + return logging.getLogger("Volume")