banch.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. # Author: XGJ2024
  2. # Date: 2025/8/14 10:32
  3. # !/usr/bin/env python3
  4. # batch_evaluator.py
  5. import os
  6. import subprocess
  7. import argparse
  8. import time
  9. import logging
  10. from pathlib import Path
  11. # 配置日志
  12. logging.basicConfig(
  13. level=logging.INFO,
  14. format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
  15. handlers=[
  16. logging.FileHandler("batch_evaluator.log"),
  17. logging.StreamHandler()
  18. ]
  19. )
  20. logger = logging.getLogger("batch_evaluator")
  21. # 固定参数配置
  22. DEFAULT_CONFIG = {
  23. "allConfigPath": r"D:\Kevin\zhaoyuan\code\zhaoyuan-master_v2.0\zhaoyuan_new\zhaoyuan\config\LST_1_all_metrics_config.yaml",
  24. "baseConfigPath": r"D:\Kevin\zhaoyuan\code\zhaoyuan-master_v2.0\zhaoyuan_new\zhaoyuan\config\LST_1_builtin_metrics_config.yaml",
  25. "customConfigPath": r"D:\Kevin\zhaoyuan\code\zhaoyuan-master_v2.0\zhaoyuan_new\zhaoyuan\config\LST_1_custom_metrics_config.yaml",
  26. "logDir": r"D:\Kevin\zhaoyuan\code\zhaoyuan-master_v2.0\zhaoyuan_new\zhaoyuan\logs",
  27. "reportPath": r"D:\Kevin\zhaoyuan\code\zhaoyuan-master_v2.0\zhaoyuan_new\zhaoyuan\reports",
  28. "plotPath": r"D:\Kevin\zhaoyuan\code\zhaoyuan-master_v2.0\zhaoyuan_new\zhaoyuan\plots",
  29. "customMetricsPath": r"D:\Kevin\zhaoyuan\code\zhaoyuan-master_v2.0\zhaoyuan_new\zhaoyuan\custom_metrics"
  30. }
  31. def run_evaluation(data_path: Path):
  32. """执行单个测试用例的评估"""
  33. try:
  34. # 构建命令行参数
  35. cmd = [
  36. "python",
  37. r"D:\Kevin\zhaoyuan\code\zhaoyuan-master_v2.0\zhaoyuan_new\zhaoyuan\scripts\evaluator_enhanced.py",
  38. "--dataPath", str(data_path),
  39. "--allConfigPath", DEFAULT_CONFIG["allConfigPath"],
  40. "--baseConfigPath", DEFAULT_CONFIG["baseConfigPath"],
  41. "--customConfigPath", DEFAULT_CONFIG["customConfigPath"],
  42. "--logDir", DEFAULT_CONFIG["logDir"],
  43. "--reportPath", DEFAULT_CONFIG["reportPath"],
  44. "--plotPath", DEFAULT_CONFIG["plotPath"],
  45. "--customMetricsPath", DEFAULT_CONFIG["customMetricsPath"]
  46. ]
  47. logger.info(f"开始评估用例: {data_path.name}")
  48. logger.debug(f"执行命令: {' '.join(cmd)}")
  49. # 执行评估
  50. start_time = time.time()
  51. # 修改这里:使用 errors='replace' 或 'ignore' 来处理编码错误,或使用 'gbk' 等其他编码
  52. result = subprocess.run(cmd, check=True, capture_output=True, text=True)
  53. elapsed_time = time.time() - start_time
  54. # 处理结果
  55. logger.info(f"用例评估完成: {data_path.name} (耗时: {elapsed_time:.1f}秒)")
  56. logger.debug(f"评估输出:\n{result.stdout}")
  57. return True
  58. except subprocess.CalledProcessError as e:
  59. logger.error(f"评估失败: {data_path.name}")
  60. logger.error(f"错误代码: {e.returncode}")
  61. logger.error(f"错误输出:\n{e.stderr}")
  62. return False
  63. except Exception as e:
  64. logger.error(f"执行异常: {str(e)}")
  65. return False
  66. def find_test_cases(parent_dir: Path):
  67. """在父目录中查找所有测试用例目录"""
  68. test_cases = []
  69. # 确保父目录存在
  70. if not parent_dir.exists():
  71. logger.error(f"父目录不存在: {parent_dir}")
  72. return test_cases
  73. # 扫描所有直接子目录
  74. for item in parent_dir.iterdir():
  75. if item.is_dir():
  76. # 检查是否包含必要的评估数据
  77. # 这里可以添加更复杂的检查逻辑
  78. if any(item.glob("*")): # 简单检查目录是否非空
  79. test_cases.append(item)
  80. else:
  81. logger.warning(f"跳过空目录: {item.name}")
  82. # 按名称排序
  83. test_cases.sort(key=lambda x: x.name)
  84. return test_cases
  85. def main():
  86. """主函数"""
  87. parser = argparse.ArgumentParser(description="批量评估系统 - 处理父目录下的所有测试用例")
  88. # parser.add_argument(
  89. # "parentDir",
  90. # default=r"D:\Kevin\zhaoyuan\data_new\LST1\二轮评测数据\单车",
  91. # type=str,
  92. # help="包含多个测试用例目录的父目录路径"
  93. # )
  94. parser.add_argument(
  95. "--parentDir", # 添加 -- 前缀改为可选参数
  96. default=r"D:\Kevin\zhaoyuan\data_new\LST1\二轮评测数据\单车",
  97. type=str,
  98. required=False, # 明确标记为非必填
  99. help="包含多个测试用例目录的父目录路径"
  100. )
  101. parser.add_argument(
  102. "--verbose", "-v",
  103. action="store_true",
  104. help="显示详细输出"
  105. )
  106. args = parser.parse_args()
  107. # 设置详细日志
  108. if args.verbose:
  109. logger.setLevel(logging.DEBUG)
  110. # 确保输出目录存在
  111. Path(DEFAULT_CONFIG["logDir"]).mkdir(parents=True, exist_ok=True)
  112. Path(DEFAULT_CONFIG["reportPath"]).mkdir(parents=True, exist_ok=True)
  113. Path(DEFAULT_CONFIG["plotPath"]).mkdir(parents=True, exist_ok=True)
  114. # 获取父目录路径
  115. parent_dir = Path(args.parentDir).resolve()
  116. logger.info("=" * 80)
  117. logger.info("开始批量评估")
  118. logger.info(f"父目录: {parent_dir}")
  119. logger.info(f"日志目录: {DEFAULT_CONFIG['logDir']}")
  120. logger.info(f"报告目录: {DEFAULT_CONFIG['reportPath']}")
  121. logger.info(f"图表目录: {DEFAULT_CONFIG['plotPath']}")
  122. logger.info("=" * 80)
  123. # 获取所有测试用例
  124. test_cases = find_test_cases(parent_dir)
  125. if not test_cases:
  126. logger.error(f"在 {parent_dir} 中未找到有效的测试用例目录")
  127. return
  128. logger.info(f"找到 {len(test_cases)} 个测试用例:")
  129. for i, case in enumerate(test_cases, 1):
  130. logger.info(f"{i}. {case.name}")
  131. # 执行评估
  132. total_count = len(test_cases)
  133. success_count = 0
  134. failed_count = 0
  135. start_time = time.time()
  136. for i, test_case in enumerate(test_cases, 1):
  137. logger.info(f"\n[处理 {i}/{total_count}] {test_case.name}")
  138. if run_evaluation(test_case):
  139. success_count += 1
  140. else:
  141. failed_count += 1
  142. # 统计结果
  143. elapsed_time = time.time() - start_time
  144. logger.info("\n" + "=" * 80)
  145. logger.info(f"批量评估完成")
  146. logger.info(f"总用例数: {total_count}")
  147. logger.info(f"成功: {success_count}")
  148. logger.info(f"失败: {failed_count}")
  149. logger.info(f"总耗时: {elapsed_time:.1f} 秒")
  150. logger.info(f"平均每用例: {elapsed_time / total_count if total_count > 0 else 0:.1f} 秒")
  151. logger.info("=" * 80)
  152. if __name__ == "__main__":
  153. main()