How to load virtualenv using the ecology module file (tcl script)?

I am trying to write a module file for a program that creates python virtualenv . To start virtualenv , you first need to run /programs/program-env/bin/activate . How to do this in modulefile ? Any help would be greatly appreciated.

Note. I tried to just put the above line into a file, and that didn't work.

Thanks,

Edit:

I am writing modulefile to download a program that can only work in virtualenv . Typically, these module files set variable names and / or add the bin directory to the path. Since the above package is slightly different, I don't know how to proceed. An example module file can be found here .

+6
source share
4 answers

Here is a slightly more complete answer based on Donal and betapatch answers that allows you to switch between two modules that do similar things:

 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;" } 

First, you need to use source .../activate , not just .../activate .

Secondly, modules has some terrible logic with swap ping modules. If you want module swap foo bar (remove foo and load bar in its place), it will actually do the following:

 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 

This means that if foo and bar are module files using virtualenvs, the second foo remove will be deactivate bar .

+6
source

The Modules system is rather strange, because what it really does is to create a set of instructions that are evaluated by the calling shell. This means that the usual ways to perform Tcl actions are often not entirely correct; this is the caller who needs to run /programs/program-env/bin/activate , not the Tcl script.

The first thing to try:

 system "/programs/program-env/bin/activate" 

However, looking between the lines in the frequently asked questions , I see that you probably need to do this (with the guards):

 if {[module-info mode] == "load"} { puts stdout "/programs/program-env/bin/activate" } 

I do not know how to cancel the operation (which is part of the module point).

+5
source

Based on Donal Fellows answers and documents, this can be done with:

 if { [ module-info mode load ] } { puts stdout "/programs/program-env/bin/activate;" } elseif { [ module-info mode remove ] } { puts stdout "deactivate;" } 

A semicolon is required.

+4
source

You didn’t explain very clearly what you are trying to do, but given your mention of the tcl script in the header, I assume that you are writing a Tcl script that needs to load the virtualenv environment to control the python script using the virtualenv configuration. Activation scripts are bash scripts that ultimately customize the current environment. You cannot just pass them to Tcl, since Tcl is not a Bourne shell. However, you can create a shell subprocess and read its environment and compare it with the environment, as it is changed after the search to activate the script. If your tcl script applies the differences to its own environment, the resulting Tcl process will be equivalent to the bash shell after the search to activate the script.

Here is an example. If you run this as tclsh scriptname bin/activate , it prints an environment in which additional settings from the activated script will now be included. In my linux box test, this added the VIRTUAL_ENV variable and changed PS1 and 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 } 
0
source

All Articles