如何构建结构化变量存储目录结构以生成程序自定义子菜单
我来给你整理一个简单直白的方案,不用复杂递归逻辑,靠os.walk()配合嵌套字典就能轻松实现结构化存储,后续生成菜单也非常好上手。
第一步:用嵌套字典构建目录-文件结构
我们可以用嵌套字典完美映射目录树:
- 字典的键是目录名/文件名
- 如果值是另一个字典,说明这是一个子目录
- 如果值是字符串,说明这是一个
.gizmo文件,字符串内容就是它的完整路径
下面是实现代码,逻辑非常清晰:
import os def build_menu_structure(root_tool_path): # 初始化根菜单结构 menu_tree = {} # 遍历目标路径下的所有目录和文件 for dirpath, dirnames, filenames in os.walk(root_tool_path): # 计算当前目录相对于根路径的相对路径,用来定位层级 relative_dir = os.path.relpath(dirpath, root_tool_path) # 定位到当前层级的字典节点 current_node = menu_tree if relative_dir != '.': # 如果不是根目录 # 把相对路径拆分成目录层级(比如"tools/sub1"拆成["tools", "sub1"]) dir_levels = relative_dir.split(os.sep) for level in dir_levels: # 如果该层级不存在就创建空字典,然后进入该层级 current_node = current_node.setdefault(level, {}) # 把当前目录下的.gizmo文件添加到当前节点 for file in filenames: if file.endswith('.gizmo'): full_file_path = os.path.join(dirpath, file) current_node[file] = full_file_path return menu_tree
举个例子,如果你的目标路径结构是:
tools/ ├─ modeling/ │ ├─ retop.gizmo │ └─ uv.unwrap.gizmo └─ rigging/ └─ ik.setup.gizmo
调用build_menu_structure("tools")后得到的menu_tree会是:
{ "modeling": { "retop.gizmo": "/full/path/tools/modeling/retop.gizmo", "uv.unwrap.gizmo": "/full/path/tools/modeling/uv.unwrap.gizmo" }, "rigging": { "ik.setup.gizmo": "/full/path/tools/rigging/ik.setup.gizmo" } }
第二步:用结构生成菜单
有了这个结构化的字典,你只需要写一个简单的递归函数,就能把它转换成程序里的菜单结构。假设你的程序提供了这两个API:
add_submenu(parent_menu, menu_name):创建子菜单,返回子菜单对象add_menu_item(parent_menu, item_name, callback):添加菜单项,点击时触发callback
那么生成菜单的代码可以这样写:
def generate_menu(menu_tree, parent_menu): for item_name, item_value in menu_tree.items(): if isinstance(item_value, dict): # 是目录,创建子菜单 sub_menu = parent_menu.add_submenu(item_name) # 递归处理子目录 generate_menu(item_value, sub_menu) else: # 是.gizmo文件,添加菜单项,item_value是完整路径 # 这里的run_gizmo需要替换成你程序里执行脚本的逻辑 parent_menu.add_menu_item( item_name, callback=lambda path=item_value: run_gizmo(path) )
额外优化建议
- 如果需要排除隐藏目录(比如以
.开头的),可以在os.walk循环里加一行:dirnames[:] = [d for d in dirnames if not d.startswith('.')] # 原地修改dirnames,跳过隐藏目录 - 要支持其他脚本类型,只需要修改
file.endswith('.gizmo')的判断条件,比如改成file.endswith(('.gizmo', '.py')) - 如果需要给菜单图标加自定义逻辑,可以在构建
menu_tree时给目录节点额外存储图标路径,比如把目录节点改成{"type": "dir", "children": {}, "icon": "path/to/icon"},不过基础版本用纯字典已经足够简单好用了。
内容的提问来源于stack exchange,提问作者Nub
相关产品推荐
相关产品推荐

