简体   繁体   English

在modulefile中加载模块时环境未修改

[英]Env not modify when loading module in modulefile

I would like to load a module into a modulefile (to resolve dependencies). 我想将模块加载到modulefile中(以解决依赖关系)。

MyModule: MyModule:

#%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

MyOtherModule: MyOtherModule:

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

When I run module load MyModule , both modules seem to be loaded but environment is not right : 当我运行module load MyModule ,两个模块似乎module load MyModule加载,但是环境不正确:

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

If I add the line foreach p [array names env] { set tmp $env($p) } or at least set tmp $env(PATH) in the MyModule after the module load MyOtherModule line, the environment is correctly modified. 如果在module load MyOtherModule行之后,在MyModule中添加foreach p [array names env] { set tmp $env($p) }或至少在module load MyOtherModule set tmp $env(PATH)module load MyOtherModule行,则正确修改了环境。 It also work fine if I don't use my function addPath but I use the prepend-path command directly, which is a bit annoying because I would like to do more things in the addPath function of course. 如果我不使用addPath函数,但直接使用prepend-path命令,它也可以正常工作,这有点烦人,因为我当然想在addPath函数中做更多的事情。

Anyone as an idea on what is going on and what I am missing ? 任何人都对正在发生的事情以及我所缺少的事情有一个想法吗?

The prepend-path is probably doing some “clever” stuff to manage a variable; prepend-path可能正在做一些“聪明”的事情来管理变量。 what exactly it is is something I don't know and don't need to know, because we can solve it all using generic Tcl. 究竟是什么我不知道也不需要知道,因为我们可以使用通用Tcl来解决所有问题。 To make your wrapping of it work, use uplevel to evaluate the code in the proper scope, though you need to consider whether to use the global scope (name #0 ) or the caller's scope ( 1 , which is the default); 为了使它的包装uplevel ,尽管需要考虑使用全局范围(名称#0 )还是调用方的范围(默认值1 ),但使用uplevel代码在适当的范围内评估代码; they're the same when your procedure addPath is called from the global level, but otherwise can be quite different, and I don't know what other oddness is going on with the modules system processing. 他们是当你的程序一样addPath从全球范围内调用,但在其他方面可能是完全不同的,我不知道还有什么其他奇怪是怎么回事的模块系统处理。

To demonstrate, try this addPath : 为了演示,请尝试以下addPath

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

We use list to construct the thing to evaluate in the caller's scope, as it is guaranteed to generate substitution-free single-command scripts. 我们使用list构造要在调用方范围内评估的事物,因为可以保证生成无替代的单命令脚本。 (And valid lists too.) This is the whole secret to doing code generation in Tcl: keep it simple, use list to do any quoting required, call a helper procedure (with suitable arguments) when things get complicated, and use uplevel to control evaluation scope. (还有有效的列表。)这是在Tcl中进行代码生成的全部秘诀:保持简单,使用list进行所需的任何引用,在情况复杂时调用帮助程序(带有合适的参数),并使用uplevel控件进行控制评价范围。

(NB: upvar can also be useful — it binds local variables to variables in another scope — but isn't what you're recommended to use here. I mention it because it's likely to be useful if you do anything more complex…) (注意: upvar也可能有用-将局部变量绑定到另一个作用域中的变量-但这不是您建议的用法。我提到它是因为如果您做更复杂的事情可能很有用……)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM