检查环境变量是否存在的良好做法是什么?

时间:2016-11-19 20:59:58

标签: python python-2.7 python-3.x if-statement environment-variables

我想在Python中检查我的环境是否存在变量,例如"FOO"。为此,我使用os标准库。在阅读了图书馆的文档后,我找到了两种方法来实现我的目标:

方法1:

if "FOO" in os.environ:
    pass

方法2:

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

我想知道哪种方法(如果有的话)是好的/首选的条件以及为什么。

7 个答案:

答案 0 :(得分:101)

使用第一个;它会直接尝试检查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")

答案 1 :(得分:14)

任何一种解决方案都有一种情况,取决于你想要以环境变量的存在为条件做什么。

案例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)

答案 2 :(得分:6)

为了安全起见,使用

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

具有上述答案的一个极端情况是设置了环境变量但为空

对于这种特殊情况,您会得到

print(os.getenv('FOO', 'bar'))
# prints nothing - 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'))"

答案 3 :(得分:1)

如果要检查是否未设置多个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))

答案 4 :(得分:0)

我建议以下解决方案。

它会打印您未包含的env var,使您可以一次全部添加它们。如果要进行for循环,则必须重新运行该程序才能查看每个丢失的变量。

from os import environ

REQUIRED_ENV_VARS = {"A", "B", "C", "D"}
diff = REQUIRED_ENV_VARS.difference(environ)
if len(diff) > 0:
    raise EnvironmentError(f'Failed because {diff} are not set')

答案 5 :(得分:0)

考虑到您正在使用一个名为 Foo 的环境变量,它可能会根据不同的环境而变化,我建议即使您使用它的值(例如 boolean ) 只是作为切换或决策标准。它可以在出现问题时为您提供帮助,或者只是为了稍后进行完整性检查。

#python=3.8

import os
import logging

foo = os.getenv("FOO")

if foo:
    logging.info(f"Proceeding since environment variable FOO exists {foo=}"
    pass
else:
    # proper action/logging based on the context
    pass

我建议不要在没有正确记录的情况下在代码本身中硬编码替代方案。使用 foo = os.getenv("FOO", "BAR") 可以默默地改变您的代码的行为。

此外,最好将所有常量放在配置文件中或作为环境变量,不要在源代码本身中硬编码任何内容。默认值和替代值可以放在配置文件中,改变环境的常量应该是 env vars,以便您可以在部署期间轻松更改它们。

答案 6 :(得分:-1)

我的评论可能与给定的标签无关。但是,我是从搜索中转到此页面的。 我一直在寻找R中的类似支票,并在@hugovdbeg帖子的帮助下提出了以下内容。我希望这对于在R中寻求类似解决方案的人会有所帮助

'USERNAME' %in% names(Sys.getenv())