游戏引擎Mod支持:如何从动态路径加载本地脚本?
动态加载Mod初始化脚本的规范实现
你的初始写法在Python里是行不通的——import语句不支持直接使用字符串拼接的动态路径。下面是几种更规范、安全的实现方式:
1. 基础实现:利用sys.path和动态导入
这种方法先将目标Mod的目录添加到Python的模块搜索路径,再导入其init.py脚本,同时加入输入校验避免安全问题:
import sys import os # 检查是否传入了Mod名称参数 if len(sys.argv) < 2: print("请指定要加载的Mod名称") sys.exit(1) mod_name = sys.argv[1].strip() # 关键:清理Mod名称,防止路径遍历攻击(比如传入"../../恶意目录") mod_name = mod_name.replace("../", "").replace("..\\", "") mod_dir = os.path.abspath(os.path.join("mods", mod_name)) # 确保Mod目录存在 if not os.path.isdir(mod_dir): print(f"Mod {mod_name}不存在或路径无效") sys.exit(1) # 将Mod目录添加到Python的模块搜索路径 sys.path.insert(0, mod_dir) try: # 导入Mod的初始化脚本 import init # 调用Mod初始化函数(假设脚本里有setup()方法) if hasattr(init, "setup"): init.setup() print(f"Mod {mod_name}加载成功") else: print(f"Mod {mod_name}的init.py缺少必要的setup()函数") except ModuleNotFoundError: print(f"Mod {mod_name}目录下没有init.py文件") except Exception as e: print(f"加载Mod {mod_name}时出错:{str(e)}")
2. 更灵活的方式:使用importlib模块
importlib是Python标准库中专门用于动态导入的模块,适合更复杂的场景:
import sys import os import importlib if len(sys.argv) < 2: print("请指定要加载的Mod名称") sys.exit(1) mod_name = sys.argv[1].strip() mod_name = mod_name.replace("../", "").replace("..\\", "") mod_path = os.path.abspath("mods") # 将mods目录添加到搜索路径,这样可以直接导入`{mod_name}.init` sys.path.insert(0, mod_path) try: # 动态导入Mod的init模块 mod_init = importlib.import_module(f"{mod_name}.init") if hasattr(mod_init, "setup"): mod_init.setup() print(f"Mod {mod_name}加载成功") except ModuleNotFoundError: print(f"Mod {mod_name}不存在或缺少init.py") except Exception as e: print(f"加载Mod {mod_name}失败:{str(e)}")
重要注意事项
- 安全优先:必须对输入的Mod名称进行清理,防止攻击者通过路径遍历访问系统敏感文件。
- 错误处理:一定要捕获导入过程中的异常,避免引擎因单个Mod加载失败而崩溃。
- 模块隔离:使用标准导入方式比直接用
exec读取脚本内容更安全,还能更好地隔离不同Mod的代码。
内容的提问来源于stack exchange,提问作者MirceaKitsune
相关产品推荐
相关产品推荐

