Подтвердить что ты не робот

Почему переменные среды, заданные в python, не сохраняются?

Я надеялся написать python script, чтобы создать некоторые подходящие переменные среды, запустив script в любом каталоге, в котором я буду выполнять некоторый код моделирования, и я прочитал, что я не могу написать script, чтобы эти env vars сохранялись в терминале mac os. Итак, две вещи:

Это правда?

и

Кажется, это было бы полезно сделать; почему это вообще невозможно?

4b9b3361

Ответ 1

Вы не можете сделать это из python, но некоторые умные трюки bash могут сделать что-то подобное. Основные аргументы таковы: переменные среды существуют в пространстве для каждого процесса. Когда новый процесс создается с помощью fork(), он наследует свои родительские переменные среды. Когда вы устанавливаете переменную среды в своей оболочке (например, bash) следующим образом:

export VAR="foo"

То, что вы делаете, сообщает bash установить переменную VAR в своем пространстве процесса на "foo". Когда вы запускаете программу, bash использует fork(), а затем exec() для запуска программы, поэтому все, что вы запускаете из bash, наследует переменные среды bash.

Теперь предположим, что вы хотите создать команду bash, которая устанавливает некоторую переменную среды DATA с содержимым из файла в вашем текущем каталоге под названием ".data". Во-первых, вам нужно иметь команду для вывода данных из файла:

cat .data

Это печатает данные. Теперь мы хотим создать команду bash для установки этих данных в переменной среды:

export DATA=`cat .data`

Эта команда принимает содержимое .data и помещает его в переменную среды DATA. Теперь, если вы поместили это внутри команды alias, у вас есть команда bash, которая устанавливает вашу переменную среды:

alias set-data="export DATA=`cat .data`"

Вы можете поместить эту команду alias внутри файлов .bashrc или .bash_profile в свой домашний каталог, чтобы эта команда была доступна в любой новой оболочке bash, которую вы запускаете.

Ответ 2

Один способ обхода - выводить команды export, а родительская оболочка оценивает это.

thescript.py:

import pipes
import random
r = random.randint(1,100)
print("export BLAHBLAH=%s" % (pipes.quote(str(r))))

.. и псевдоним bash (то же самое можно сделать и в большинстве оболочек.. даже tcsh!):

alias setblahblahenv="eval $(python thescript.py)"

Использование:

$ echo $BLAHBLAH

$ setblahblahenv
$ echo $BLAHBLAH
72

Вы можете вывести любой произвольный код оболочки, включая несколько команд, например:

export BLAHBLAH=23 SECONDENVVAR='something else' && echo 'everything worked'

Помните, что будьте осторожны с тем, чтобы избежать любого динамически созданного вывода (для этого подходит модуль pipes.quote)

Ответ 3

Если вы задаете переменные среды внутри python script (или любой другой script или программы), это не повлияет на родительскую оболочку.

Изменить пояснения: Поэтому ответ на ваш вопрос - да, это правда. Однако вы можете экспортировать его из оболочки script и указать ее с помощью вызова точки

в fooexport.sh

export FOO="bar"

в командной строке

$ . ./fooexport.sh
$ echo $FOO
bar

Ответ 4

Что мне нравится делать, это использовать /usr/bin/env в оболочке script, чтобы "обернуть" мою командную строку, когда я окажусь в подобных ситуациях:

#!/bin/bash

/usr/bin/env NAME1="VALUE1" NAME2="VALUE2" ${*}

Итак, позвольте этому script "myappenv". Я поместил его в мой каталог $HOME/bin, который у меня есть в моей $PATH.

Теперь я могу вызвать любую команду, используя эту среду, просто добавив "myappenv" как таковой:

myappenv dosometask -xyz

Другие опубликованные решения тоже работают, но это мои личные предпочтения. Одно из преимуществ заключается в том, что среда является временной, поэтому, если я работаю в оболочке, только вызываемая мной команда зависит от измененной среды.

Модифицированная версия, основанная на новых комментариях

#!/bin/bash

/usr/bin/env G4WORKDIR=$PWD ${*}

Вы можете обернуть это все в псевдоним. Я предпочитаю метод обёртки script, так как у меня, как правило, есть и другая среда, в которой я готов поддерживать.

Ответ 5

Это вообще не возможно. Новый процесс, созданный для python, не может повлиять на среду его родительского процесса. Родитель не может влиять на ребенка, но родитель получает настройку дочерней среды как часть нового процесса создания.

Возможно, вы можете установить их в .bashrc, .profile или эквивалент "выполняется при входе в систему" ​​или "выполняется в каждом новом сеансе терминала" script в MacOS.

Вы также можете запустить python программу моделирования с требуемой средой. (используйте параметр env для подпроцесса .Popen(http://docs.python.org/library/subprocess.html))

import subprocess, os
os.chdir('/home/you/desired/directory')
subprocess.Popen(['desired_program_cmd', 'args', ...], env=dict(SOMEVAR='a_value') )

Или вы могли бы написать python оболочку script, как это, в файл с расширением .sh:

export SOMEVAR=a_value
cd /home/you/desired/directory
./desired_program_cmd

а затем chmod +x и запустите его из любого места.

Ответ 6

Как ответил Бенсон, но лучший способ взлома - создать простую функцию bash для сохранения аргументов:

upsert-env-var (){ eval $(python upsert_env_var.py $*); }

Вы можете делать все, что хотите, в своем python script с помощью аргументов. Чтобы просто добавить переменную, используйте что-то вроде:

var = sys.argv[1]
val = sys.argv[2]
if os.environ.get(var, None):
    print "export %s=%s:%s" % (var, val, os.environ[var])
else:
    print "export %s=%s" % (var, val)

Использование:

upsert-env-var VAR VAL