У меня есть скрипт, который выглядит примерно так:
export foo=/tmp/foo
export bar=/tmp/bar
Каждый раз, когда я собираю, я запускаю ' source init_env '(где init_env - вышеописанный скрипт) для установки некоторых переменных.
Чтобы выполнить то же самое в Python, у меня был запущен этот код,
reg = re.compile('export (?P<name>\w+)(\=(?P<value>.+))*')
for line in open(file):
m = reg.match(line)
if m:
name = m.group('name')
value = ''
if m.group('value'):
value = m.group('value')
os.putenv(name, value)
Но затем кто-то решил, что было бы неплохо добавьте строку, подобную следующей, в файл init_env
:
export PATH="/foo/bar:/bar/foo:$PATH"
Очевидно, мой скрипт на Python развалился. Я мог бы изменить скрипт Python для обработки этой строки, но потом он просто сломается, когда кто-то придумает новую функцию для использования в файле init_env
.
Вопрос в том, есть ли простой способ запустить команду Bash и позволить ей изменить мой os.environ
?
Проблема с вашим подходом в том, что вы пытаетесь интерпретировать сценарии bash. Сначала вы просто пытаетесь интерпретировать оператор экспорта. Затем вы замечаете, что люди используют расширение переменных. Позже люди будут помещать в свои файлы условные обозначения или обрабатывать замены. В конце концов, у вас будет полноценный интерпретатор сценариев bash с кучей ошибок. Не делай этого.
Пусть Bash интерпретирует файл за вас, а затем соберет результаты.
Вы можете сделать это следующим образом:
#! /usr/bin/env python
import os
import pprint
import shlex
import subprocess
command = shlex.split("env -i bash -c 'source init_env && env'")
proc = subprocess.Popen(command, stdout = subprocess.PIPE)
for line in proc.stdout:
(key, _, value) = line.partition("=")
os.environ[key] = value
proc.communicate()
pprint.pprint(dict(os.environ))
Убедитесь, что вы обрабатываете ошибки в случае, если bash не работает с исходным init_env
, или сам bash не может выполняться, или подпроцесс не может выполнить bash, или любой другой ошибки.
env -i
в начале командной строки создает чистую среду. это означает, что вы получите переменные среды только из init_env
. если вам нужна унаследованная системная среда, опустите env -i
.
Подробнее читайте в документации по подпроцессу .
Примечание: это будет захватывать только переменные, установленные с помощью оператора export
, поскольку env
печатает только экспортированные переменные.
Наслаждайтесь.
Обратите внимание, что в документации Python говорится, что если вы хотите манипулировать средой, вы должны манипулировать os.environ
напрямую вместо использования os.putenv ()
. Я считаю это ошибкой, но я отвлекся.
Вместо того, чтобы иметь в качестве источника сценария Python сценарий bash, было бы проще и элегантнее иметь источник сценария оболочки init_env
, а затем запускать сценарий Python с измененным окружающая обстановка.
#!/bin/bash
source init_env
/run/python/script.py