检查环境变量是不是存在的好习惯是啥?

Posted

技术标签:

【中文标题】检查环境变量是不是存在的好习惯是啥?【英文标题】:What is a good practice to check if an environmental variable exists or not?检查环境变量是否存在的好习惯是什么? 【发布时间】:2017-04-03 12:43:37 【问题描述】:

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

方法一:

if "FOO" in os.environ:
    pass

方法二:

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

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

【问题讨论】:

它主要基于意见。两者都有相同的目的。我会更喜欢方法 1,因为它更干净 我不能说里面有任何东西。选择一个(掷硬币?),如果它不起作用,稍后重新评估。坦率地说,我认为您输入此问题所花费的时间比您节省的时间都多! @Ayoub:我想你忘了看问题 “在 Python 中检查环境变量是否存在的好习惯是什么?” 基于意见。方法 1 语法效果更好,因为您询问 foo 是否在环境变量中,而不是寻找 foo 导致 None 值。 但这种方式可能并不明显,除非你是荷兰人...... 【参考方案1】:

考虑到您正在使用一个名为 Foo 的环境变量,它可能会根据不同的环境而变化,我建议您获取它的值并 INFO(或 DEBUG)记录它,即使您只使用它的值(例如布尔值)作为切换或决策标准。它可以在出现问题或稍后进行健全性检查时为您提供帮助。

#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 var,以便您可以在部署期间轻松更改它们。

【讨论】:

【参考方案2】:

我推荐以下解决方案。

它会打印您未包含的环境变量,这样您就可以一次将它们全部添加。如果你使用 for 循环,你将不得不重新运行程序以查看每个丢失的 var。

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')

【讨论】:

您不需要检查差异的长度,只需使用if diff: 就可以了(也许将diff 更改为missing_variables 以获得更具描述性的名称)。同样在 python 3.8 及更高版本中,您可以使用 walrus 运算符对其进行更多压缩:if missing_variables := REQUIRED_ENV_VARS.difference(environ):. 绝招!注意 var 类型 dict 而不是 list @MarkHu 其实是set 类型。 print(type('a', 'b', 'c')) 产生 <class 'set'> 作为输出。【参考方案3】:

我的评论可能与给定的标签无关。然而,我是从我的搜索中被引导到这个页面的。 我在 R 中寻找类似的检查,在@hugovdbeg 帖子的帮助下我想出了以下内容。我希望它对在 R 中寻找类似解决方案的人有所帮助

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

【讨论】:

【参考方案4】:

如果您想检查是否未设置多个环境变量,您可以执行以下操作:

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

【讨论】:

【参考方案5】:

为了安全起见

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):,所以如果是这样,那应该允许默认 vs 开头的 or 语法 @Chris McKee 试试这个>>> import os; os.environ['FOO'] = ''; print(os.getenv('FOO', 'bar')) 误导性方法签名? @Chris McKee,另一个例子$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"【参考方案6】:

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

【讨论】:

感谢您的解释。我会记住这一点。【参考方案7】:

这两种解决方案都有一个案例,具体取决于您要根据环境变量的存在执行什么操作。

案例一

当您想纯粹根据环境变量的存在来采取不同的行动,而不关心它的值时,第一个解决方案是最佳实践。它简洁地描述了您测试的内容:环境变量列表中的“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,它允许基于键合并多个字典。 ChainMap 文档中有一个这样的例子:

[...]
combined = ChainMap(command_line_args, os.environ, defaults)

【讨论】:

以上是关于检查环境变量是不是存在的好习惯是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查环境变量是不是存在并获取其值? [复制]

csh 成语检查环境变量是不是存在?

检查环境变量是不是存在并设置为 True [关闭]

检查 EJS 模板中是不是存在变量的正确方法是啥(使用 ExpressJS)?

在 C# 中检查 double 是不是为整数的好方法是啥? [复制]

配置java环境变量的作用是啥?