从我的python脚本在集群上加载环境模块

时间:2019-01-10 01:07:36

标签: python slurm

我需要将python作业提交到服务器。在运行时,我需要在运行时加载和卸载模块,因为它调用了多个程序,每个程序具有不同的依赖项,即gcc与intel冲突。

这个问题曾经被问过,但是在这种情况下答案对我没有用

Loading environment modules within a python script

loading-environment-modules-within-a-python-script

我尝试使用

import subprocess as sub
cmd = 'module load intel/2016.4'
p = sub.Popen(cmd, shell=True, stderr = sub.STDOUT, stdout = sub.PIPE).communicate()[0] 
print(p.decode()) # this simply outputs to screen

然后,输出显示模块已切换。

Lmod is automatically replacing "gcc/5.4.0" with "intel/2016.4".

Due to MODULEPATH changes, the following have been reloaded:
  1) openmpi/2.1.1

但是,当我从终端执行“模块列表”时,模块尚未切换。 gcc/5.4.0仍在加载。另外,要求intel/2016.4的程序无法运行。例如,稍后,我希望能够使用需要intel/2016.4且无法运行的gromacs版本。

我有点困惑,因为我认为我可以通过Popen使用bash命令,而“模块加载”是bash命令。我不想编写bash脚本来执行此操作,在脚本中使用python比bash更方便地完成了很多其他事情。

2 个答案:

答案 0 :(得分:2)

大多数环境模块实现都有一个非常方便的Python初始化脚本。对于lmod,它在$LMOD_DIR/../init中,并命名为env_modules_python.py。因此,您可以这样做:

$ export PYTHONPATH=${PYTHONPATH}:$LMOD_DIR/../init
$ python
Python 2.7.5 (default, Jul 13 2018, 13:06:57)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from env_modules_python import module

,从那里您可以直接在Python中运行任何“模块”命令。

>>> module('list')

Currently Loaded Modules:

[...]
  3) StdEnv                                             (H)
  4) GCCcore/6.4.0                                      (H)
  5) binutils/2.28-GCCcore-6.4.0                        (H)
[...]

它将修改Python脚本的环境,并且该环境将传播到子shell。

>>> import os
>>> os.system("which icc")
which: no icc in (/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin)
256
>>> module("load intel")
>>> os.system("which icc")
/opt/[...]/icc/2017.4.196-GCC-6.4.0-2.28/compilers_and_libraries_2017.4.196/linux/bin/intel64/icc
0

Popen相同:

>>> import subprocess as sub
>>> cmd='which icc'
>>> p = sub.Popen(cmd, shell=True, stderr = sub.STDOUT, stdout = sub.PIPE).communicate()[0]
>>> print(p.decode())
/opt/[...]icc/2017.4.196-GCC-6.4.0-2.28/compilers_and_libraries_2017.4.196/linux/bin/intel64/icc

答案 1 :(得分:1)

我最近遇到了这个问题。解决此问题的一种简单方法是在所需命令之前包含依赖项,并用分号分隔它们

cmd = 'module load intel/2016.4; "gromacs command"'
p = sub.Popen(cmd, shell=True, stderr = sub.STDOUT, stdout = sub.PIPE).communicate()[0]

其中,“ gromacs命令”表示您通常将其称为gromacs。 intel/2016.4不会在模块列表中显示为已加载,如果您在运行脚本后进行检查,但是gromacs将使用您想要的intel/2016.4从python脚本内部运行。