Загрузка модулей среды в скрипте Python
Есть ли способ для скрипта Python загружать и использовать модули среды? os.system('module load xxx')
не работает, так как выполняет их в подоболочке (по крайней мере, я так думаю)
5 ответов
Я знаю, что этот вопрос довольно старый, но он все еще достаточно актуален, чтобы я искал ответ, поэтому я публикую то, что я нашел, что также работает:
По крайней мере, в источниках 3.2.9+ вы можете включить файл init "python", чтобы получить версию модуля с функцией python:
>>> execfile('/usr/local/Modules/default/init/python.py')
>>> module('list')
No Modulefiles Currently Loaded.
>>> module('load','foo')
>>> module('list')
Currently Loaded Modulefiles:
1) foo/1.0
Мне сказали, что более ранние версии могут делать то же самое без расширения.py, но это из вторых рук, так что ymmv.
Альтернативное расположение файла init (из комментария @lib): /usr/share/Modules/init/python.py
Один из наших администраторов смог решить проблему для меня, используя os.popen()
звонки в modulecmd
:
cmd = os.popen('/path/to/modulecmd python load my-module')
exec(cmd)
Хотя принятое решение работает, мне было проще написать:
import sys
sys.path.insert(0, '/path/to/environment/modules')
# Environment modules become available by loading python.py (the name choice could be better here)
import python as mod
# ...
mod.module('use', '/some/dir')
mod.module('load', 'program/1.2.3')
Мне это кажется более питоническим, а также позволяет IDE предлагать автозаполнение и т. Д.
Я нашел ответы от jnewman, andreee и ian очень полезными. Однако в моем случае$MODULESHOME/init/python.py
написан на Python 2 и несовместим с Python 3 (он используетexec output
вместоexec(output)
). Вот моя модифицированная версия, поддерживающая Python 3:
import os
import subprocess
def load_module(module_name, *, capture_output=True, check=True, **kw):
module_home = os.environ["MODULESHOME"]
modulecmd = os.path.join(module_home, "bin/modulecmd")
process = subprocess.run(
[modulecmd, "python", "load", module_name],
capture_output=capture_output,
check=check,
**kw,
)
return process
Пример использования:
CONDA_MODULE = "Anaconda3/2022.05"
load_module(CONDA_MODULE)
print(subprocess.check_output(["conda", "--help"], stderr=subprocess.STDOUT).decode("utf8"))
Не напрямую, но вот один из возможных обходных путей, в зависимости от вашей среды. Предполагая, что вы можете предварять вашу системную команду с ENVVAR=value
Вы можете сделать что-то вроде этого:
import os
os.environ['EDITOR'] = 'vi'
cmd = "EDITOR=%(EDITOR)s $EDITOR" % os.environ
os.system(cmd)
Код назначает vi вашей переменной среды EDITOR, затем передает ее в командную строку и запускает команду, которая (в данном случае) - EDITOR.