Загрузка модулей среды в скрипте 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.

Другие вопросы по тегам