Как правильно проверить, существует ли переменная среды или нет?

130

Я хочу проверить свою среду на наличие переменной, скажем "FOO", в Python. Для этого я использую osстандартную библиотеку. Прочитав документацию библиотеки, я выяснил 2 способа достижения своей цели:

Способ 1:

if "FOO" in os.environ:
    pass

Способ 2:

if os.getenv("FOO") is not None:
    pass

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

Кшитидж Сараоги
источник
В первую очередь это мнение. Оба служат одной цели. Я предпочитаю метод 1, так как он чище
Мойнуддин Квадри
1
Не могу сказать, что в этом что-то есть. Выберите один (подбросьте монетку?) И пересмотрите позже, если окажется, что это не сработает. Честно говоря, я думаю, что вы потратили больше времени на ввод этого вопроса, чем вы бы сэкономили!
jonrsharpe
1
@Ayoub: Я думаю, вы забыли увидеть вопрос «Как лучше всего проверять, существует ли переменная среды в Python?»
Moinuddin Quadri
1
Основано на мнении. Синтаксис метода 1 работает лучше, так как вы спрашиваете, fooнаходится ли он в env vars, а не ищет ли fooрезультаты в Noneзначениях.
Uriel
1
Но этот путь может быть не очевиден, если вы не голландец ...
jonrsharpe

Ответы:

168

Используйте первое; он напрямую пытается проверить, определено ли что-то в environ. Хотя вторая форма работает одинаково хорошо, ей не хватает семантики, поскольку вы получаете обратно значение, если оно существует, и только используете его для сравнения.

Вы пытаетесь увидеть , если что - то присутствует в environ , почему вы получите только сравнить его , а затем бросить его подальше ?

Это именно то, что getenvделает:

Получить переменную окружения , вернуть, Noneесли ее не существует. Необязательный второй аргумент может указывать альтернативное значение по умолчанию.

(это также означает, что ваш чек может быть просто if getenv("FOO"))

вы не хотите его получать , вы хотите проверить его существование.

В любом случае, getenvэто просто оболочка, environ.getно вы не видите людей, проверяющих членство в сопоставлениях с помощью:

from os import environ
if environ.get('Foo') is not None:

Подводя итог, используйте:

if "FOO" in os.environ:
    pass

если вы просто хотите проверить существование, тогда используйте, getenv("FOO")если вы действительно хотите что-то сделать со значением, которое вы можете получить.

Димитрис Фасаракис Хиллиард
источник
2
Спасибо за ваше объяснение. Я буду иметь это в виду.
Кшитидж Сараоги
29

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

Случай 1

Если вы хотите предпринять различные действия исключительно на основе существования переменной среды, не обращая внимания на ее значение, первое решение - лучший способ. Он кратко описывает, что вы проверяете: есть ли «FOO» в списке переменных среды.

if 'KITTEN_ALLERGY' in os.environ:
    buy_puppy()
else:
    buy_kitten()

Случай 2

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

server = os.getenv('MY_CAT_STREAMS', 'youtube.com')

или возможно

server = os.environ.get('MY_CAT_STREAMS', 'youtube.com')

Обратите внимание: если у вас есть несколько вариантов для вашего приложения, вы можете захотеть изучить ChainMap, что позволяет объединить несколько dicts на основе ключей. Пример этого есть в ChainMapдокументации:

[...]
combined = ChainMap(command_line_args, os.environ, defaults)
hugovdberg
источник
15

На всякий случай используйте

os.getenv('FOO') or 'bar'

Угловой случай с приведенными выше ответами - это когда переменная среды установлена, но пуста

Для этого особого случая вы получаете

print(os.getenv('FOO', 'bar'))
# prints new line - though you expected `bar`

или

if "FOO" in os.environ:
    print("FOO is here")
# prints FOO is here - however its not

Чтобы этого избежать, просто используйте or

os.getenv('FOO') or 'bar'

Тогда вы получите

print(os.getenv('FOO') or 'bar')
# bar

Когда у нас есть пустые переменные среды?

Вы забыли установить значение в .envфайле

# .env
FOO=

или экспортировано как

$ export FOO=

или забыл установить это в settings.py

# settings.py
os.environ['FOO'] = ''

Обновление: если сомневаетесь, посмотрите эти однострочные

>>> import os; os.environ['FOO'] = ''; print(os.getenv('FOO', 'bar'))

$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"
Левон
источник
Подпись для getenv такова, def getenv(key, default=None):что если да, то вначале должно быть разрешено использование синтаксиса по умолчанию и or
Крис Макки,
@Chris McKee попробуй это>>> import os; os.environ['FOO'] = ''; print(os.getenv('FOO', 'bar'))
Левон
Сигнатура метода, вводящего в заблуждение 😜
Крис Макки
1
@Chris McKee, другой пример$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"
Левон
3

Если вы хотите проверить, не заданы ли несколько переменных env, вы можете сделать следующее:

import os

MANDATORY_ENV_VARS = ["FOO", "BAR"]

for var in MANDATORY_ENV_VARS:
    if var not in os.environ:
        raise EnvironmentError("Failed because {} is not set.".format(var))
vhamon
источник
-1

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

'USERNAME' %in% names(Sys.getenv())
sveer
источник