【问题标题】:Env not modify when loading module in modulefile在模块文件中加载模块时,环境不修改
【发布时间】:2014-05-21 13:42:01
【问题描述】:

我想将一个模块加载到一个模块文件中(以解决依赖关系)。

我的模块:

#%Module########################################
##
##  Modulefile
#
proc ModulesHelp { } {
    puts stderr "Env for MyProg"
}
proc addPath {var val} {
    prepend-path $var $val
}
module load MyOtherModule 
addPath   PATH   /opt/MyModule/bin

我的其他模块:

#%Module########################################
##
##  Modulefile
#
proc ModulesHelp { } {
    puts stderr "Env for MyOtherProg"
}
proc addPath {var val} {
    prepend-path $var $val
}
addPath   PATH   /opt/MyOtherModule/bin

当我运行module load MyModule 时,两个模块似乎都已加载但环境不正确:

$module list
Currently Loaded Modulefiles:
  1) MyModule   2) MyOtherModule
$echo $PATH
/opt/MyModule/bin:/usr/bin:/bin

如果我在 module load MyOtherModule 行之后的 MyModule 中添加 foreach p [array names env] { set tmp $env($p) } 或至少 set tmp $env(PATH) 行,则环境已正确修改。如果我不使用我的函数addPath,它也可以正常工作,但我直接使用prepend-path 命令,这有点烦人,因为我当然想在addPath 函数中做更多的事情。

任何人都知道发生了什么以及我错过了什么?

【问题讨论】:

    标签: environment-variables tcl environment-modules modulefile


    【解决方案1】:

    prepend-path 可能正在做一些“聪明”的事情来管理变量;它到底是什么我不知道也不需要知道,因为我们可以使用通用 Tcl 解决所有问题。为了使你的包装工作,使用uplevel在适当的范围内评估代码,尽管你需要考虑是使用全局范围(名称#0)还是调用者的范围(1,这是默认);当从全局级别调用您的过程 addPath 时,它们是相同的,但否则可能会相当不同,而且我不知道模块系统处理还会发生什么其他奇怪的事情。

    为了演示,试试这个addPath

    proc addPath {var val} {
        puts stderr "BEFORE..."
        uplevel 1 [list prepend-path $var $val]
        puts stderr "AFTER..."
    }
    

    我们使用list 来构造要在调用者范围内评估的事物,因为它保证生成无替换的单命令脚本。 (还有有效列表。)这是在 Tcl 中进行代码生成的全部秘诀:保持简单,使用 list 进行任何需要的引用,当事情变得复杂时调用帮助程序(带有合适的参数),并使用 @ 987654330@控制评估范围。

    (注意:upvar 也很有用——它将局部变量绑定到另一个作用域中的变量——但这不是你在这里推荐使用的。我提到它是因为如果你做任何事情它可能会很有用更复杂……)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-15
      • 1970-01-01
      • 2019-12-26
      相关资源
      最近更新 更多