检查环境变量是不是存在的好习惯是啥?
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)
【讨论】:
以上是关于检查环境变量是不是存在的好习惯是啥?的主要内容,如果未能解决你的问题,请参考以下文章
检查 EJS 模板中是不是存在变量的正确方法是啥(使用 ExpressJS)?