Commit c7524571 by Yuhaibo

1

parent a179dd7d
# 调试语句清理报告
**清理时间**: 2025-11-26 20:31:38
**备份目录**: backups\cleanup_20251126_203137
## 清理统计
- 扫描文件总数: 108
- 修改文件数量: 58
- 删除语句总数: 540
## 详细清理记录
| 文件 | 删除数量 |
|------|----------|
| handlers\modelpage\model_test_handler.py | 85 |
| handlers\videopage\missionpanel_handler.py | 46 |
| handlers\modelpage\model_training_handler.py | 37 |
| handlers\videopage\general_set_handler.py | 33 |
| widgets\datasetpage\datapreprocess_panel.py | 30 |
| handlers\videopage\amplify_window_handler.py | 20 |
| widgets\videopage\general_set.py | 20 |
| widgets\modelpage\training_page.py | 17 |
| handlers\modelpage\test_integration.py | 14 |
| handlers\modelpage\tools\test_dat_conversion.py | 13 |
| handlers\modelpage\tools\test_bat_model.py | 12 |
| handlers\modelpage\tools\test_pt_detection.py | 12 |
| handlers\cleanup_debug_statements.py | 11 |
| widgets\videopage\channelpanel.py | 11 |
| widgets\videopage\missionpanel.py | 11 |
| handlers\datasetpage\crop_preview_handler.py | 10 |
| handlers\app.py | 9 |
| handlers\datasetpage\test_realtime_monitoring.py | 9 |
| widgets\datasetpage\datacollection_panel.py | 9 |
| widgets\datasetpage\test_labelme_integration.py | 9 |
| widgets\datasetpage\crop_preview_panel.py | 8 |
| handlers\modelpage\tools\test_bat_image_detection.py | 7 |
| handlers\modelpage\tools\test_dat_image_detection.py | 7 |
| handlers\videopage\thread_manager\result_distributor.py | 6 |
| widgets\locate_debug_statements.py | 6 |
| widgets\style_manager.py | 6 |
| widgets\videopage\curvepanel.py | 6 |
| handlers\datasetpage\datacollection_channel_handler.py | 5 |
| handlers\videopage\mock_physical_zoom_controller.py | 5 |
| handlers\videopage\detection.py | 4 |
| handlers\videopage\thread_manager\threads\display_thread.py | 4 |
| widgets\videopage\historyvideopanel.py | 4 |
| handlers\modelpage\cleanup_test_code.py | 3 |
| handlers\modelpage\model_trainingworker_handler.py | 3 |
| handlers\videopage\channelpanel_handler.py | 3 |
| handlers\videopage\curvepanel_handler.py | 3 |
| handlers\videopage\test_handler.py | 3 |
| handlers\videopage\HK_SDK\test_hikcapture.py | 3 |
| handlers\videopage\thread_manager\threads\storage_thread.py | 3 |
| handlers\videopage\thread_manager\threads\test_model_loading.py | 3 |
| widgets\datasetpage\annotationtool.py | 3 |
| widgets\datasetpage\crop_config_dialog.py | 3 |
| widgets\datasetpage\videobrowser.py | 3 |
| widgets\datasetpage\videoclipper.py | 3 |
| handlers\view_handler.py | 2 |
| handlers\modelpage\model_page_handler.py | 2 |
| handlers\modelpage\model_set_handler.py | 2 |
| widgets\modelpage\modelset_page.py | 2 |
| handlers\datasetpage\datapreprocess_handler.py | 1 |
| handlers\videopage\HK_SDK\FocusControl.py | 1 |
| handlers\videopage\HK_SDK\HCNetSDK.py | 1 |
| handlers\videopage\HK_SDK\HKcapture.py | 1 |
| handlers\videopage\thread_manager\thread_manager.py | 1 |
| widgets\menubar.py | 1 |
| widgets\datasetpage\test_crop_preview_integration.py | 1 |
| widgets\datasetpage\training_panel.py | 1 |
| widgets\videopage\logicsetting_dialogue.py | 1 |
| widgets\videopage\modelsetting_dialogue.py | 1 |
# 调试语句清理工具使用说明
## 工具简介
`cleanup_debug_statements.py` 是一个智能化的调试语句清理脚本,可以自动删除项目中的调试代码,同时保留功能性代码。
## 功能特性
### ✅ 会删除的内容
1. **调试print语句**
- 包含调试关键词: `🔍``调试``DEBUG``debug``测试``test`
- 包含调试标记: `[调试]``[DEBUG]``[测试]`
- 空print语句或只打印分隔线的语句
2. **调试日志语句**
- `logging.debug(...)`
- `logger.debug(...)`
3. **调试注释**
- 包含调试关键词的注释
- 不包含重要标记的调试注释
### ❌ 不会删除的内容
1. **功能性输出**
- 包含: `错误``警告``成功``失败``完成`
- 包含: `ERROR``WARNING``INFO`
2. **重要注释**
- `TODO``FIXME``XXX``HACK``NOTE`
3. **普通代码**
- 所有非调试的正常代码
## 使用方法
### 1. 运行脚本
```bash
# 在项目根目录下运行
python handlers/cleanup_debug_statements.py
```
### 2. 确认操作
脚本会显示清理规则并要求确认:
```
是否继续清理? (y/n):
```
输入 `y` 继续,输入 `n` 取消。
### 3. 查看结果
清理完成后会显示:
- 扫描文件总数
- 修改文件数量
- 删除语句总数
- 备份目录位置
## 安全保障
### 自动备份
- 每次运行都会创建完整备份
- 备份位置: `backups/cleanup_YYYYMMDD_HHMMSS/`
- 保留原始文件的完整目录结构
### 恢复方法
如果需要恢复,只需从备份目录复制文件回来:
```bash
# 示例: 恢复单个文件
cp backups/cleanup_20251126_203000/handlers/app.py handlers/app.py
# 示例: 恢复整个目录
cp -r backups/cleanup_20251126_203000/handlers/* handlers/
```
## 清理报告
脚本会生成详细的清理报告: `handlers/CLEANUP_REPORT.md`
报告内容包括:
- 清理时间
- 备份目录
- 清理统计
- 每个文件的详细清理记录(按删除数量排序)
## 示例
### 会被删除的代码
```python
# 调试print
print(f"🔍 [调试] 变量值: {value}")
print(f"[DEBUG] 进入函数")
print("="*60) # 分隔线
# 调试日志
logging.debug("调试信息")
logger.debug(f"变量: {var}")
# 调试注释
# 🔍 调试: 这里需要检查
# DEBUG: 临时代码
```
### 会被保留的代码
```python
# 功能性输出
print(f"❌ 错误: {error_msg}")
print(f"✅ 操作成功")
logging.info("程序启动")
# 重要注释
# TODO: 需要优化性能
# FIXME: 修复边界情况
# NOTE: 这是重要说明
# 普通代码
result = process_data(input_data)
```
## 注意事项
1. **首次使用建议**
- 先在测试分支运行
- 检查清理结果
- 确认无误后再应用到主分支
2. **排除目录**
- 自动排除: `__pycache__`, `.git`, `venv`, `env`, `backups`, `database`
- 只处理 `.py` 文件
3. **保守策略**
- 默认采用保守策略
- 不确定的语句不会删除
- 优先保留而非删除
## 自定义配置
如需修改清理规则,可以编辑脚本中的以下部分:
```python
# 调试关键词(会被删除)
self.debug_keywords = [
r'🔍', r'调试', r'DEBUG', r'debug', r'测试', r'test',
# 添加更多关键词...
]
# 保留关键词(不会被删除)
self.keep_keywords = [
r'TODO', r'FIXME', r'XXX', r'HACK', r'NOTE',
r'错误', r'警告', r'成功', r'失败', r'完成',
# 添加更多关键词...
]
```
## 技术支持
如遇到问题:
1. 检查备份目录是否正常创建
2. 查看清理报告了解详细信息
3. 从备份恢复文件
4. 调整清理规则后重新运行
---
**最后更新**: 2025-11-26
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
智能调试语句清理脚本
自动删除项目中的调试print语句、logging.debug()和调试注释
保留功能性代码,创建备份,生成详细报告
"""
import os
import re
import shutil
from datetime import datetime
from pathlib import Path
class DebugStatementCleaner:
"""调试语句清理器"""
def __init__(self, project_root):
"""
初始化清理器
Args:
project_root: 项目根目录路径
"""
self.project_root = Path(project_root)
self.backup_dir = self.project_root / 'backups' / f'cleanup_{datetime.now().strftime("%Y%m%d_%H%M%S")}'
self.report = {
'total_files': 0,
'modified_files': 0,
'total_removals': 0,
'files_detail': []
}
# 调试关键词模式(用于识别调试print语句)
self.debug_keywords = [
r'🔍', r'调试', r'DEBUG', r'debug', r'测试', r'test',
r'⚠️.*调试', r'✅.*调试', r'❌.*调试', r'📝.*调试',
r'\[调试\]', r'\[DEBUG\]', r'\[测试\]'
]
# 需要保留的关键词(功能性输出)
self.keep_keywords = [
r'TODO', r'FIXME', r'XXX', r'HACK', r'NOTE',
r'错误', r'警告', r'成功', r'失败', r'完成',
r'ERROR', r'WARNING', r'INFO'
]
def should_remove_print(self, line):
"""
判断print语句是否应该删除
Args:
line: 代码行
Returns:
bool: True表示应该删除
"""
# 去除前导空格
stripped = line.strip()
# 不是print语句,不删除
if not stripped.startswith('print('):
return False
# 检查是否包含保留关键词
for keyword in self.keep_keywords:
if re.search(keyword, line, re.IGNORECASE):
return False
# 检查是否包含调试关键词
for keyword in self.debug_keywords:
if re.search(keyword, line):
return True
# 空print语句或只打印分隔线的,删除
if re.match(r'^\s*print\(\s*["\']?\s*[=\-*#]{3,}\s*["\']?\s*\)\s*$', line):
return True
# 默认不删除(保守策略)
return False
def should_remove_logging_debug(self, line):
"""
判断logging.debug语句是否应该删除
Args:
line: 代码行
Returns:
bool: True表示应该删除
"""
stripped = line.strip()
# 删除所有logging.debug和logger.debug
if re.match(r'^\s*(logging|logger)\.debug\(', stripped):
return True
return False
def should_remove_comment(self, line):
"""
判断注释是否应该删除
Args:
line: 代码行
Returns:
bool: True表示应该删除
"""
stripped = line.strip()
# 不是注释,不删除
if not stripped.startswith('#'):
return False
# 检查是否包含保留关键词
for keyword in self.keep_keywords:
if re.search(keyword, line, re.IGNORECASE):
return False
# 检查是否包含调试关键词
for keyword in self.debug_keywords:
if re.search(keyword, line):
return True
# 默认不删除
return False
def clean_file(self, file_path):
"""
清理单个文件
Args:
file_path: 文件路径
Returns:
int: 删除的语句数量
"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
except Exception as e:
print(f"❌ 读取文件失败: {file_path}, 错误: {e}")
return 0
new_lines = []
removed_count = 0
i = 0
while i < len(lines):
line = lines[i]
# 检查是否需要删除
should_remove = (
self.should_remove_print(line) or
self.should_remove_logging_debug(line) or
self.should_remove_comment(line)
)
if should_remove:
removed_count += 1
# 如果删除后会产生空行,也删除空行
if i > 0 and i < len(lines) - 1:
prev_line = lines[i - 1].strip()
next_line = lines[i + 1].strip() if i + 1 < len(lines) else ''
# 如果前后都是空行,跳过当前行
if not prev_line and not next_line:
i += 1
continue
else:
new_lines.append(line)
i += 1
# 如果有修改,写回文件
if removed_count > 0:
# 创建备份
self._backup_file(file_path)
# 写入清理后的内容
try:
with open(file_path, 'w', encoding='utf-8') as f:
f.writelines(new_lines)
except Exception as e:
print(f"❌ 写入文件失败: {file_path}, 错误: {e}")
return 0
return removed_count
def _backup_file(self, file_path):
"""
备份文件
Args:
file_path: 文件路径
"""
try:
# 创建备份目录
self.backup_dir.mkdir(parents=True, exist_ok=True)
# 计算相对路径
rel_path = Path(file_path).relative_to(self.project_root)
backup_path = self.backup_dir / rel_path
# 创建备份文件的父目录
backup_path.parent.mkdir(parents=True, exist_ok=True)
# 复制文件
shutil.copy2(file_path, backup_path)
except Exception as e:
print(f"⚠️ 备份文件失败: {file_path}, 错误: {e}")
def clean_directory(self, directory, exclude_dirs=None):
"""
清理目录下的所有Python文件
Args:
directory: 目录路径
exclude_dirs: 排除的目录列表
"""
if exclude_dirs is None:
exclude_dirs = ['__pycache__', '.git', 'venv', 'env', 'backups', 'database']
directory = Path(directory)
for root, dirs, files in os.walk(directory):
# 排除特定目录
dirs[:] = [d for d in dirs if d not in exclude_dirs]
for file in files:
if file.endswith('.py'):
file_path = Path(root) / file
self.report['total_files'] += 1
removed = self.clean_file(file_path)
if removed > 0:
self.report['modified_files'] += 1
self.report['total_removals'] += removed
rel_path = file_path.relative_to(self.project_root)
self.report['files_detail'].append({
'file': str(rel_path),
'removed': removed
})
print(f"✅ {rel_path}: 删除 {removed} 处调试语句")
def generate_report(self):
"""生成清理报告"""
report_path = self.project_root / 'handlers' / 'CLEANUP_REPORT.md'
with open(report_path, 'w', encoding='utf-8') as f:
f.write("# 调试语句清理报告\n\n")
f.write(f"**清理时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
f.write(f"**备份目录**: {self.backup_dir.relative_to(self.project_root)}\n\n")
f.write("## 清理统计\n\n")
f.write(f"- 扫描文件总数: {self.report['total_files']}\n")
f.write(f"- 修改文件数量: {self.report['modified_files']}\n")
f.write(f"- 删除语句总数: {self.report['total_removals']}\n\n")
if self.report['files_detail']:
f.write("## 详细清理记录\n\n")
f.write("| 文件 | 删除数量 |\n")
f.write("|------|----------|\n")
# 按删除数量排序
sorted_details = sorted(
self.report['files_detail'],
key=lambda x: x['removed'],
reverse=True
)
for detail in sorted_details:
f.write(f"| {detail['file']} | {detail['removed']} |\n")
print(f"\n📊 清理报告已生成: {report_path}")
def print_summary(self):
"""打印清理摘要"""
print("\n" + "="*70)
print("📊 清理完成摘要")
print("="*70)
print(f"扫描文件总数: {self.report['total_files']}")
print(f"修改文件数量: {self.report['modified_files']}")
print(f"删除语句总数: {self.report['total_removals']}")
print(f"备份目录: {self.backup_dir.relative_to(self.project_root)}")
print("="*70 + "\n")
def main():
"""主函数"""
# 获取项目根目录
script_dir = Path(__file__).parent
project_root = script_dir.parent
print("="*70)
print("🧹 智能调试语句清理工具")
print("="*70)
print(f"项目路径: {project_root}")
print("\n清理规则:")
print(" ✅ 删除包含调试关键词的print语句(🔍、调试、DEBUG等)")
print(" ✅ 删除所有logging.debug()和logger.debug()")
print(" ✅ 删除包含调试关键词的注释")
print(" ✅ 保留功能性输出(错误、警告、成功等)")
print(" ✅ 保留重要注释(TODO、FIXME、XXX等)")
print(" ✅ 自动创建备份")
print("="*70 + "\n")
# 确认操作
response = input("是否继续清理? (y/n): ").strip().lower()
if response != 'y':
print("❌ 操作已取消")
return
# 创建清理器
cleaner = DebugStatementCleaner(project_root)
# 清理handlers目录
print("\n🔍 开始清理 handlers/ 目录...")
handlers_dir = project_root / 'handlers'
if handlers_dir.exists():
cleaner.clean_directory(handlers_dir)
# 清理widgets目录
print("\n🔍 开始清理 widgets/ 目录...")
widgets_dir = project_root / 'widgets'
if widgets_dir.exists():
cleaner.clean_directory(widgets_dir)
# 生成报告
cleaner.generate_report()
# 打印摘要
cleaner.print_summary()
print("✅ 清理完成!")
print(f"💡 如需恢复,请查看备份目录: {cleaner.backup_dir.relative_to(project_root)}")
if __name__ == '__main__':
main()
...@@ -2048,188 +2048,3 @@ class AnnotationWidget(QtWidgets.QWidget): ...@@ -2048,188 +2048,3 @@ class AnnotationWidget(QtWidgets.QWidget):
def showAnnotationError(self, message): def showAnnotationError(self, message):
"""显示标注错误(由handler调用)""" """显示标注错误(由handler调用)"""
pass pass
if __name__ == "__main__":
"""独立调试入口"""
import sys
app = QtWidgets.QApplication(sys.argv)
# 测试1: 面板嵌入式使用
print("=" * 50)
print("测试模式1: 面板嵌入到主窗口")
print("=" * 50)
main_window = QtWidgets.QMainWindow()
main_window.setWindowTitle("GeneralSetPanel 组件测试 - 嵌入式")
main_window.resize(1000, 800)
# 创建组件
panel = GeneralSetPanel(main_window)
panel.setChannelInfo("通道1", "channel1", {'task_id': 'TASK001', 'task_name': '制冷任务'})
# 连接信号用于测试
def on_task_info_changed(info):
print(f"[测试] 任务信息变化: {info}")
def on_area_count_changed(count):
print(f"[测试] 区域个数变化: {count}")
def on_annotation_requested():
"""测试标注功能 - 直接弹出标注界面"""
print(f"[测试] 请求开始标注")
# 创建测试图像
import cv2
import numpy as np
test_frame = np.zeros((720, 1280, 3), dtype=np.uint8)
test_frame[:] = (100, 120, 140) # 灰色背景
# 添加一些文字说明(使用英文,因为cv2.putText不支持中文)
cv2.putText(test_frame, "Test Annotation Frame", (50, 50),
cv2.FONT_HERSHEY_SIMPLEX, 1.5, (255, 255, 255), 2)
cv2.putText(test_frame, "Draw detection areas and mark liquid levels", (50, 100),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (200, 200, 200), 1)
# 添加一些测试区域
cv2.rectangle(test_frame, (200, 200), (400, 400), (0, 255, 0), 2)
cv2.rectangle(test_frame, (500, 300), (700, 500), (0, 0, 255), 2)
print(" 测试图像创建完成,包含中文说明文字")
# 创建标注界面组件
annotation_widget = AnnotationWidget(main_window, None)
# 连接信号
def on_annotation_completed(boxes, bottoms, tops):
pass
# 更新面板的标注状态
panel.updateAnnotationStatus(True, len(boxes))
QtWidgets.QMessageBox.information(
main_window,
"标注完成",
f"成功标注 {len(boxes)} 个检测区域\n\n"
f"标注结果已保存到面板中"
)
def on_annotation_cancelled():
pass
annotation_widget.annotationCompleted.connect(on_annotation_completed)
annotation_widget.annotationCancelled.connect(on_annotation_cancelled)
# 加载测试图像并显示
if annotation_widget.loadFrame(test_frame):
annotation_widget.show()
print("[测试] 标注界面已显示")
else:
QtWidgets.QMessageBox.warning(
main_window,
"测试失败",
"无法加载测试图像到标注界面"
)
def on_detection_start_requested():
"""测试检测开始功能"""
QtWidgets.QMessageBox.information(
main_window,
"开始检测",
"检测功能已启动!\n\n正在加载标注区域并开始液位检测..."
)
# 添加信号连接处理(独立调试时需要)
def on_load_channel_model_config(channel_id):
print(f"[测试] 请求加载通道模型配置: {channel_id}")
# 独立调试时不加载实际配置,只打印日志
def on_auto_save_model_path(model_path):
print(f"[测试] 请求自动保存模型路径: {model_path}")
# 独立调试时不保存实际配置,只打印日志
panel.taskInfoChanged.connect(on_task_info_changed)
panel.areaCountChanged.connect(on_area_count_changed)
panel.annotationRequested.connect(on_annotation_requested)
panel.detectionStartRequested.connect(on_detection_start_requested)
panel.loadChannelModelConfigRequested.connect(on_load_channel_model_config)
panel.autoSaveModelPathRequested.connect(on_auto_save_model_path)
main_window.setCentralWidget(panel)
main_window.show()
# 添加一个简单的测试按钮来直接测试标注界面
test_button = QtWidgets.QPushButton("测试标注界面")
test_button.clicked.connect(on_annotation_requested)
panel.layout().addWidget(test_button)
# 可选:添加一个按钮来测试对话框模式
def test_dialog():
dialog = GeneralSetDialog(
main_window,
channel_name="通道2",
task_info={'task_id': 'TASK002', 'task_name': '测试任务'}
)
if dialog.exec_() == QtWidgets.QDialog.Accepted:
settings = dialog.getSettings()
pass
else:
pass
# 添加测试按钮到状态栏
test_dialog_btn = QtWidgets.QPushButton("测试对话框模式")
test_dialog_btn.clicked.connect(test_dialog)
main_window.statusBar().addPermanentWidget(test_dialog_btn)
def test_annotation_widget():
"""测试标注界面组件"""
# 创建测试图像
import cv2
import numpy as np
test_frame = np.zeros((720, 1280, 3), dtype=np.uint8)
test_frame[:] = (100, 120, 140) # 灰色背景
# 添加一些文字说明
cv2.putText(test_frame, "Test Annotation Frame", (50, 50),
cv2.FONT_HERSHEY_SIMPLEX, 1.5, (255, 255, 255), 2)
cv2.putText(test_frame, "Draw detection areas and mark liquid levels", (50, 100),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (200, 200, 200), 1)
# 创建标注界面组件
annotation_widget = AnnotationWidget(main_window, None)
# 连接信号
def on_annotation_completed(boxes, bottoms, tops):
pass
QtWidgets.QMessageBox.information(
main_window,
"标注完成",
f"成功标注 {len(boxes)} 个检测区域"
)
def on_annotation_cancelled():
pass
annotation_widget.annotationCompleted.connect(on_annotation_completed)
annotation_widget.annotationCancelled.connect(on_annotation_cancelled)
# 加载测试图像并显示
if annotation_widget.loadFrame(test_frame):
annotation_widget.show()
print("[测试] 标注界面已显示")
else:
QtWidgets.QMessageBox.warning(
main_window,
"测试失败",
"无法加载测试图像到标注界面"
)
test_annotation_btn = QtWidgets.QPushButton("测试标注界面")
test_annotation_btn.clicked.connect(test_annotation_widget)
main_window.statusBar().addPermanentWidget(test_annotation_btn)
sys.exit(app.exec_())
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment