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

Loading environment modules on a cluster from my python script

我需要向服务器提交 python 作业。虽然它是 运行ning,但我需要在它 运行 时加载和卸载模块,因为它调用了多个程序,每个程序都有不同的依赖项,这些依赖项会发生冲突,即 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

但是,当我从终端执行 'module list' 时,模块没有切换。 gcc/5.4.0 仍在加载中。此外,需要 intel/2016.4 的程序无法 运行。例如,稍后我希望能够使用需要 intel/2016.4 的 gromacs 版本,但它失败了。

我有点困惑,因为我认为我可以通过 Popen 使用 bash 命令,而 'module load' 是一个 bash 命令。我不想编写 bash 脚本来执行此操作,在我的脚本中还有很多其他事情用 python 比 bash 更方便。

我最近 运行 喜欢这个。一个简单的解决方法是在你想要的命令之前包含依赖项,并用分号分隔它们

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

其中 "gromacs command" 表示您通常会调用 gromacs。 intel/2016.4 不会在模块列表中显示为已加载,如果您在 运行 脚本之后检查,但 gromacs 将 运行 从您的 python 脚本中使用 intel/2016.4,这就是你想要的。

大多数环境模块实现都有一个非常方便的 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' 命令。

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