102 lines
4.2 KiB
Python
102 lines
4.2 KiB
Python
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已返回主菜单")
|