Как установить переменные среды в Python

Мне нужно установить некоторые переменные окружения в скрипте python, и я хочу, чтобы все другие скрипты, которые вызываются из python (сценарии оболочки), которые будут дочерним процессом, будут видеть установленные переменные окружения. Значение является числом.

Если я сделаю os.environ["DEBUSSY"] = 1жалуется, говоря, что 1 должен быть строкой. Я также хочу знать, как читать переменные окружения в python (в более поздней части скрипта), как только я его установлю.

20 ответов

Переменные среды должны быть строками, поэтому используйте

os.environ["DEBUSSY"] = "1"

установить переменную DEBUSSY в строку 1, Чтобы получить доступ к этой переменной позже, просто используйте

print os.environ["DEBUSSY"]

Дочерние процессы автоматически наследуют среду родительского процесса - никаких специальных действий с вашей стороны не требуется.

Возможно, вам придется рассмотреть некоторые дополнительные аспекты надежности кода;

когда вы сохраняете целочисленную переменную как переменную окружения, попробуйте

os.environ['DEBUSSY'] = str(myintvariable)

затем для извлечения учтите, что во избежание ошибок следует попробовать

os.environ.get('DEBUSSY', 'Not Set')

возможно заменить -1 на "Не установлено"

так что, чтобы положить все это вместе

myintvariable = 1
os.environ['DEBUSSY'] = str(myintvariable)
strauss = int(os.environ.get('STRAUSS', '-1'))
# NB KeyError <=> strauss = os.environ['STRAUSS']
debussy = int(os.environ.get('DEBUSSY', '-1'))

print "%s %u, %s %u" % ('Strauss', strauss, 'Debussy', debussy)

os.environ ведет себя как словарь Python, так что все общие словарные операции могут быть выполнены. В добавок к get а также set операции, упомянутые в других ответах, мы также можем просто проверить, существует ли ключ

Python 2

>>> import os
>>> os.environ.has_key('HOME')  # Check an existing env. variable
True
>>> os.environ.has_key('FOO')   # Check for a non existing variable
False
>>> os.environ['FOO'] = '1'     # Set a new env. variable (String value)
>>> os.environ.has_key('FOO')
True
>>> os.environ.get('FOO')       # Retrieve the value
'1'

Python 3

Для python 3 словари используют ключевое слово in вместо has_key

>>> import os
>>> 'HOME' in os.environ  # Check an existing env. variable
True
...

Есть одна важная вещь, которую стоит отметить при использовании os.environ:

Хотя дочерние процессы наследуют среду от родительского процесса, я недавно столкнулся с проблемой и выяснил, если у вас есть другие сценарии, обновляющие среду во время работы вашего сценария python, вызывая os.environ снова не будет отражать последние значения.

Выдержка из документов:

Это сопоставление фиксируется при первом импорте модуля os, обычно во время запуска Python, как часть обработки site.py. Изменения в среде, сделанные после этого времени, не отражаются в os.environ, за исключением изменений, внесенных путем непосредственного изменения os.environ.

os.environ.data который хранит все переменные окружения, является объектом dict, который содержит все значения окружения:

>>> type(os.environ.data)  # changed to _data since v3.2 (refer comment below)
<type 'dict'>

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

import os
os.environ["variable_1"] = "value_1"
os.environ["variable_2"] = "value_2"
# To Verify above code
os.environ.get("variable_1")
os.environ.get("variable_2")

Этот простой блок кода работает хорошо, однако эти переменные существуют внутри соответствующих процессов, поэтому вы не найдете их на вкладке переменных среды в настройках системы Windows. В значительной степени приведенный выше код не служил моей цели. Эта проблема обсуждается здесь: проблема сохранения переменных

os.environ.putenv(key, value)

Очередная неудачная попытка. Итак, наконец, мне удалось успешно сохранить переменную в регистре среды окна, имитируя команды оболочки Windows, заключенные в системный класс пакета os. Следующий код описывает эту успешную попытку.

os.system("SETX {0} {1} /M".format(key, value))

Я надеюсь, что это будет полезно для некоторых из вас.

если я делаю os.environ["DEBUSSY"] = 1, он жалуется, говоря, что 1 должен быть строкой.

Тогда делай

os.environ["DEBUSSY"] = "1"

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

Просто используйте os.environ["DEBUSSY"], как в

some_value = os.environ["DEBUSSY"]

Установить переменную:

Метод назначения элемента по ключу:

import os    
os.environ['DEBUSSY'] = '1'  #Environ Variable must be string not Int

получить или проверить, существует ли он или нет,

так как os.environ - это экземпляр, вы можете попробовать объектный путь.

Способ 1:

os.environ.get('DEBUSSY') # this is error free method if not will return None by default

получите '1' как возвращаемое значение

Способ 2:

os.environ['DEBUSSY'] # will throw an key error if not found!

Способ 3:

'DEBUSSY' in os.environ  # will return Boolean True/False

Способ 4:

os.environ.has_key('DEBUSSY') #last 2 methods are Boolean Return so can use for conditional statements

Вы должны присвоить строковое значение переменной среды.

os.environ["DEBUSSY"] = "1"

Если вы хотите прочитать или распечатать переменную окружения, просто используйте

print os.environ["DEBUSSY"]

Эти изменения вступят в силу только для текущего процесса, которому он был назначен, и не изменит значение навсегда. Дочерние процессы автоматически наследуют среду родительского процесса.

введите описание изображения здесь

Как насчет os.environ["DEBUSSY"] = '1'? Переменные среды всегда являются строками.

Следует отметить, что если вы попытаетесь установить для переменной среды оценку bash, она не сохранит то, что вы ожидаете. Пример:

from os import environ

environ["JAVA_HOME"] = "$(/usr/libexec/java_home)"

Это не будет оценивать его, как в оболочке, поэтому вместо получения /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home в качестве пути вы получите буквальное выражение $(/usr/libexec/java_home).

Обязательно оцените его перед установкой переменной окружения, например:

from os import environ
from subprocess import Popen, PIPE

bash_variable = "$(/usr/libexec/java_home)"
capture = Popen(f"echo {bash_variable}", stdout=PIPE, shell=True)
std_out, std_err = capture.communicate()
return_code = capture.returncode

if return_code == 0:
    evaluated_env = std_out.decode().strip()
    environ["JAVA_HOME"] = evaluated_env
else:
    print(f"Error: Unable to find environment variable {bash_variable}")

Вы можете использовать os.environ словарь для доступа к переменным среды.

Теперь проблема у меня была в том, что если бы я попытался использовать os.system чтобы запустить пакетный файл, который устанавливает переменные вашей среды (используя команду SET в файле **.bat*), он на самом деле не установит их для вашей среды Python (но для дочернего процесса, который создается с помощью os.system функция). Чтобы получить переменные, установленные в среде python, я использую этот скрипт:

import re
import system
import os

def setEnvBat(batFilePath, verbose = False):
    SetEnvPattern = re.compile("set (\w+)(?:=)(.*)$", re.MULTILINE)
    SetEnvFile = open(batFilePath, "r")
    SetEnvText = SetEnvFile.read()
    SetEnvMatchList = re.findall(SetEnvPattern, SetEnvText)

    for SetEnvMatch in SetEnvMatchList:
        VarName=SetEnvMatch[0]
        VarValue=SetEnvMatch[1]
        if verbose:
            print "%s=%s"%(VarName,VarValue)
        os.environ[VarName]=VarValue

Когда вы играете с переменными среды (добавляете / модифицируете / удаляете переменные), хорошей практикой является восстановление предыдущего состояния при завершении функции.

Вам может понадобиться что-то вроде modified_environ контекстный менеджер опишу в этом вопросе для восстановления переменных среды.

Классическое использование:

with modified_environ(DEBUSSY="1"):
    call_my_function()

Установите переменные среды следующим образом:

      import os

 # Set environment variables
 os.environ['API_USER'] = 'username'
 os.environ['API_PASSWORD'] = 'secret'

 # Get environment variables
 USER = os.getenv('API_USER')
 PASSWORD = os.environ.get('API_PASSWORD')

Использовать setdefault функция для установки новой переменной, если переменная не существует в среде.

убедитесь, что вы установили переменную среды как строку, а не int. Иначе выкину TypeError.

      import os

if not os.environ.get("DEBUSSY"):
    os.environ.setdefault("DEBUSSY","1")
else:
     os.environ["DEBUSSY"] = "1"

print(os.environ["DEBUSSY"])

Аккуратный способ управления переменными среды, определяемыми пользователем, состоит в том, чтобы поместить их все в текстовый файл и загрузить во время выполнения. Мы можем добиться этого с помощью пакета python-dotenv , который позволяет нам импортировать эти переменные. Этот пакет можно установить через

pip установить python-dotenv

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

      DEBUSSY=1    
PATH_TO_EXECUTABLE=/home/user_name/project/run.sh

Затем импортируйте их в свою среду следующим образом:

      from dotenv import load_dotenv
load_dotenv()

Вы можете указать путь к файлу, содержащему определенные переменные, в качестве необязательного аргумента для load_dotenv . Впоследствии к этим переменным среды можно будет получить обычный доступ через модуль os .

Я написал этот аккуратный маленький менеджер контекста для установки переменных только на время блока с отступом:

      import os
from contextlib import contextmanager

@contextmanager
def extended_env(new_env_vars):
    old_env = os.environ.copy()
    os.environ.update(new_env_vars)
    yield
    os.environ.clear()
    os.environ.update(old_env)

Пример использования (надеюсь, кроссплатформенный):

      import subprocess

subprocess.run("echo $ENVTESTO %ENVTESTO%", shell=True)

with extended_env({"ENVTESTO": "17"}):
    subprocess.run("echo $ENVTESTO %ENVTESTO%", shell=True)

subprocess.run("echo $ENVTESTO %ENVTESTO%", shell=True)

А что насчет следующего?

      os.environ["DEBUSSY"] = '1'
debussy = int(os.environ.get('DEBUSSY'))
print(type(debussy))

<класс 'целое число'>

Поздний ответ, который может помочь кому-то быстро протестировать без изменений кода. Просто запустите свое приложение с прикрепленной переменной среды следующим образом:

       $ DEBUSSY=1 python3 api.py

Вы можете передавать env vars таким образом в любой скрипт.

Есть хорошее готовое решение Python под названием pycrosskit . Он создаст переменные среды, которые будут постоянными как для Linux, так и для Windows.

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

      # Will Set Persistent Value for Variable in System
# * subkey works only for windows like file in folder
# * reg_path works only for windows as register path 
SysEnv.set_var(name, value, subkey, reg_path=default_reg_path)

# Will Get Persistent Value for Variable in System
# * reg_path works only for windows as register path
# * delete, deletes key from environment and its subkeys after read
SysEnv.get_var(name, reg_path=default_reg_path, delete=False)

Если у вас возникли проблемы с Flask и unittest, помните, что если вы устанавливаете переменную вне любого метода, эта переменная читается при импорте приложения. Это может показаться тривиальным, но может кому-то избавить от головной боли.

Например, если в вашем Flask unittest вы:

  1. импортировать приложение
  2. установите переменную среды в setUp метод.
  3. использовать app.test_client() протестировать ваше приложение

Переменная второго шага не будет видна на третьем шаге, потому что переменная уже считана, когда вы выполняете первый шаг.

Среда замораживается для самого кода (а не для дочерних процессов) и не может быть выполнена программно.

Хорошим решением, независимо от платформы, является перенос вызова python в пакетный файл. Например: если бы я работал в Linux, пакетный файл мог бы выглядеть так:

      export "DEBUSSY"="1"
python mycode.py
Другие вопросы по тегам