import os import json import logging import time from .visualizer import generate_visualization # 配置日志 logging.basicConfig(level=logging.INFO, format='%(message)s') def run_json_visualization(): print("\n🚀 进入 JSON 文件可视化模式") print("说明: 读取包含行为树(Pytree)结构的 JSON 文件并生成 PNG 图片。") print(" 支持的 JSON 结构: 直接是 Pytree 根节点对象,或包含 'root'/'data' 字段的对象。") while True: try: file_path = input("\n请输入 JSON 文件路径 (输入 'q' 返回): ").strip() if file_path.lower() in ['q', 'exit', 'quit']: break if not file_path: continue # 处理相对路径 if not os.path.isabs(file_path): # 尝试相对于当前工作目录 if not os.path.exists(file_path): # 尝试相对于 tools/test_validate base_dir = os.path.dirname(os.path.dirname(__file__)) alt_path = os.path.join(base_dir, file_path) if os.path.exists(alt_path): file_path = alt_path if not os.path.exists(file_path): print(f"❌ 文件不存在: {file_path}") continue if not os.path.isfile(file_path): print(f"❌ 路径不是一个文件: {file_path}") continue print(f"📖 正在读取: {file_path}") try: with open(file_path, 'r', encoding='utf-8') as f: data = json.load(f) except json.JSONDecodeError as e: print(f"❌ JSON 解析失败: {e}") continue except Exception as e: print(f"❌ 读取文件失败: {e}") continue # 尝试提取 root 节点 root_node = None # 情况 1: 顶层就是 root 节点 (包含 name 和 type) if isinstance(data, dict) and 'name' in data and 'type' in data: root_node = data print("ℹ️ 识别到顶层即为 Pytree 根节点") # 情况 2: 包含 root 字段 elif isinstance(data, dict) and 'root' in data: root_node = data['root'] print("ℹ️ 从 'root' 字段提取节点") # 情况 3: 包含 data 字段,data 里有 root elif isinstance(data, dict) and 'data' in data and isinstance(data['data'], dict) and 'root' in data['data']: root_node = data['data']['root'] print("ℹ️ 从 'data.root' 字段提取节点") # 情况 4: 包含 data 字段,data 本身就是 root elif isinstance(data, dict) and 'data' in data and isinstance(data['data'], dict) and 'name' in data['data']: root_node = data['data'] print("ℹ️ 从 'data' 字段提取节点") if not root_node: print("❌ 无法识别 Pytree 结构。JSON 对象必须包含 'name' 和 'type' 字段,或在 'root'/'data' 字段中包含它们。") continue # 生成输出路径 dir_name = os.path.dirname(file_path) base_name = os.path.splitext(os.path.basename(file_path))[0] output_path = os.path.join(dir_name, f"{base_name}.png") print("🎨 正在生成可视化...") if generate_visualization(root_node, output_path): print(f"✅ 可视化图已生成: {output_path}") # 尝试打开图片 (仅限支持的系统) # if os.name == 'posix': # os.system(f"xdg-open '{output_path}'") else: print("❌ 生成失败,请检查 graphviz 是否安装正确") except KeyboardInterrupt: print("\n已取消") break except Exception as e: print(f"❌ 发生未预期的错误: {e}") print("\n已返回主菜单")