2

We have a number of different versions of python which we module load. These can be a vanilla python 2 or 3 install, or an anaconda version with a whole load of extra libraries.

At the moment, if I write a script which requires me to use a specific python install (which I find using module load python/ana ; which python), I have to #! to an explicit path. For example

#!/path/to/anaconda/1.7.0/64/bin/python

points to the current version of python which is loaded when I do module load python/anaconda at the moment.

This module is not managed by me however, so if someone updates the module to use /path/to/anaconda/1.7.1/64/bin/python then deletes 1.7.0, my script will stop working.

Is there a standard way for a script to specify both the interpreter to use and the module the interpreter should be loaded from? Something like

#!/blah/module_env python/anaconda python -c

Alternatively, are there any other options which don't need root access? Our enterprise linux machines are locked down so that we can't install our own software, or change /use/bin/env configuration, just module load software which has been made available.

  • Perhaps try module spider python to see what versions of python you have available? You can also type which python and use that path as the shebang line. – BarocliniCplusplus Jul 27 '17 at 15:11
  • I found lots of environment modules questions here on Unix & Linux @StephenKitt, and started to tag them, any reason why you don't want an environment-modules tag? – Mark Booth Jul 28 '17 at 13:55
  • @Mark I don’t have anything against a new tag, if it’s useful, but the way you started tagging the questions wasn’t scrutable to anyone but you: there was no tag description, and no link to the relevant software. Feel free to resurrect the tag, but please document it first. – Stephen Kitt Jul 28 '17 at 14:02
  • That's precisely how I found the location of the module loaded python in the first place @BarocliniCplusplus. I've edited my question to make that clear. Also, we are using standard environment modules, not an alternative implementation such as Lmod as implied by your module spider reference. – Mark Booth Jul 28 '17 at 14:07
  • Sorry @StephenKitt, I hadn't got around to that writing up tag details, and all of my suggested edits were rejected. I'll give it another go when I have the time to do it properly. – Mark Booth Jul 28 '17 at 14:09
2

I'm not familiar with that module software of yours, but it looks like you should be able to do something like:

#! /bin/sh -
'eval' '. "$MODULES_HOME/init/sh"; module load something || exit; exec python -- "$0" "$@"'

python script follows

That will be first interpreted by sh which will then call module and execute python on the same script and with the same arguments.

The first two lines will be ignored by python, the first one because it's a comment, the second because it's just the concatenation of two strings.

More generally:

#! /bin/sh -
'eval' 'single-line-of-shell-code-with-no-single-quote; exec python -- "$0" "$@"'

Is a generic way to have an executable python script where some preamble shell code is run beforehand. For multiline shell code, you can also use python's '''...''' quotes:

#! /bin/sh -
':' '''python script with shell preamble'

arbitrary shell code here provided it doesn't contain
a sequence of 3 single quotes.

exec python -- "$0" "$@"
'''

print("Hello World")

So here:

#! /bin/sh -
':' '''python script with shell preamble'
"$MODULES_HOME/init/sh"
module load something || exit
exec python -- "$0" "$@"
'''

python script follows

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.