Red语言do/do-file函数为何改变执行路径致模块加载失败?
为什么Red语言的
do函数会改变当前执行路径? 这确实是Red里一个容易踩坑的细节——do函数在加载外部文件时,会自动将当前工作目录切换到被加载文件所在的路径,这就是你加载完modules/b.red后,再加载modules/c.red失败的核心原因:此时你的工作目录已经变成了modules/,再执行do %modules/c.red就会去modules/modules/目录找文件,自然找不到。
为什么会有这种设计?
Red的这个行为是为了让被加载的脚本能正常使用自身目录下的相对路径引用。比如如果b.red里有一行do %utils/helper.red,当do切换到modules/目录后,这个相对路径就能正确找到modules/utils/helper.red,而不需要写复杂的绝对路径。但这种设计在批量加载多个文件时,就会引发路径混乱。
解决方法
这里有几个可靠的方案来避免这个问题:
使用绝对路径加载
先获取当前脚本所在的绝对路径,然后拼接成目标文件的绝对路径再加载,这样不管当前工作目录怎么变,都能准确找到文件:; 获取当前脚本的所在目录(带末尾斜杠) script-root: system/script/path ; 用绝对路径加载模块 do rejoin [script-root "modules/b.red"] do rejoin [script-root "modules/c.red"]保存并恢复工作目录
在加载文件前先保存当前的工作目录,加载完成后再切换回去,这样后续的路径引用就不会受影响:; 保存原始工作目录 original-dir: system/path ; 加载第一个模块 do %modules/b.red ; 切回原始目录 system/path: original-dir ; 加载第二个模块(此时路径恢复正常) do %modules/c.red读取文件内容后执行
do
如果被加载的脚本不需要依赖自身目录的相对路径,可以先读取文件内容,再用do执行字符串形式的代码,这种方式不会改变当前工作目录:do read %modules/b.red do read %modules/c.red
额外提示
如果你用的是do-file函数,要注意它和do的行为是一致的——同样会切换工作目录,所以上面的方案对do-file也完全适用。
内容的提问来源于stack exchange,提问作者Mateusz Palichleb
相关产品推荐
相关产品推荐

