我正在尝试为创建python virtualenv
的程序编写模块文件。要启动virtualenv
,首先需要运行/programs/program-env/bin/activate
。我如何在modulefile
中执行此操作?
任何帮助将不胜感激。
注意:我尝试将上面一行放在文件中,但它没有用。
谢谢,
编辑:
我正在编写modulefile来加载只能在virtualenv
中运行的程序。通常,这些模块文件将设置变量名称和/或将bin目录添加到路径。由于上述包装有所不同,我不知道如何继续。可以找到示例模块文件here。
答案 0 :(得分:8)
这是一个稍微更完整的答案,建立在Donal和betapatch的答案之上,它允许您在两个执行类似操作的模块之间进行交换:
if { [module-info mode load] || [module-info mode switch2] } {
puts stdout "source /programs/program-env/bin/activate;"
} elseif { [module-info mode remove] && ![module-info mode switch3] } {
puts stdout "deactivate;"
}
首先,您需要使用source .../activate
而不仅仅是.../activate
。
其次,当modules
ping模块时,swap
有一些可怕的逻辑。如果您想要module swap foo bar
(删除foo
并在其位置加载bar
),它实际上会执行以下操作:
foo: switch1 # prep for remove
foo: remove # actually remove
bar: switch2 # load new module
foo: switch3 # cleanup
foo: remove # happens at the same time as foo switch3
这意味着,如果foo
和bar
都是使用virtualenvs的模块文件,则第二个foo remove
将deactivate
bar
。
答案 1 :(得分:4)
根据Donal Fellows的回答和文件可以完成:
if { [ module-info mode load ] } {
puts stdout "/programs/program-env/bin/activate;"
} elseif { [ module-info mode remove ] } {
puts stdout "deactivate;"
}
分号是必不可少的。
答案 2 :(得分:0)
你没有非常清楚地解释你想要做什么,但鉴于你在标题中提到了一个tcl脚本,我假设你正在编写一个Tcl脚本,需要加载virtualenv环境来使用virtualenv配置来操作python脚本。激活脚本是最终设置当前环境的bash脚本。你不能简单地将它们整合到Tcl中,因为Tcl不是Bourne shell。但是,您可以创建一个shell子流程并读取其环境,并将其与在激活脚本源之后更改的环境进行比较。如果您的tcl脚本将差异应用于其自己的环境,则在获取激活脚本后,生成的Tcl进程将等同于bash shell。
这是一个例子。如果您将其作为tclsh scriptname bin/activate
运行,则会打印环境,该环境现在将包含激活脚本中的其他设置。在我对linux盒子的测试中,这增加了一个VIRTUAL_ENV变量并修改了PS1和PATH。
#!/usr/bin/env tclsh
# Load a virtualenv script in a subshell and apply the environment
# changes to the current process environment.
proc read_env {chan varname} {
upvar #0 $varname E
set len [gets $chan line]
if {$len < 0} {
fileevent $chan readable {}
set ::completed 1
} else {
set pos [string first = $line]
set key [string range $line 0 [expr {$pos - 1}]]
set val [string range $line [expr {$pos + 1}] end]
set E($key) $val
}
}
proc read_shell_env {varname cmd} {
set shell [open |[list /bin/bash] "r+"]
fconfigure $shell -buffering line -encoding utf-8 -blocking 0
fileevent $shell readable [list read_env $shell $varname]
puts $shell $cmd
flush $shell
vwait ::completed
close $shell
return
}
proc update_env {key val} {
global env
set env($key) $val
}
proc load_virtualenv {filename} {
array set ::envA {}
array set ::envB {}
read_shell_env ::envA "printenv; exit 0"
read_shell_env ::envB "source \"$filename\"; printenv; exit 0"
set keys [lsort [array names ::envA]]
foreach k [lsort [array names ::envB]] {
if {[info exists ::envA($k)]} {
if {$::envA($k) ne $::envB($k)} {
update_env $k $::envB($k)
}
} else {
update_env $k $::envB($k)
}
}
unset ::envA
unset ::envB
return
}
proc main {filename} {
global env
load_virtualenv $filename
foreach key [lsort [array names env]] {
puts "$key=$env($key)"
}
return 0
}
if {!$tcl_interactive} {
set r [catch [linsert $argv 0 main] err]
if {$r} {puts stderr $err}
exit $r
}