我想在Python中检查我的环境是否存在变量,例如"FOO"
。为此,我使用os
标准库。在阅读了图书馆的文档后,我找到了两种方法来实现我的目标:
方法1:
if "FOO" in os.environ:
pass
方法2:
if os.getenv("FOO") is not None:
pass
我想知道哪种方法(如果有的话)是好的/首选的条件以及为什么。
答案 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)
任何一种解决方案都有一种情况,取决于你想要以环境变量的存在为条件做什么。
当你想纯粹基于环境变量的存在而采取不同的行动时,不考虑其价值,第一种解决方案是最佳实践。它简洁地描述了您测试的内容:环境变量列表中的“FOO”。
if 'KITTEN_ALLERGY' in os.environ:
buy_puppy()
else:
buy_kitten()
如果要在环境变量中未定义值时设置默认值,则第二个解决方案实际上很有用,但不是在您编写的表单中:
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())