How can I evaluate if a env variable is a boolean True, in Python? Is it correct to use:
if os.environ['ENV_VAR'] is True:
.......
I think this works well:
my_env = os.getenv("ENV_VAR", 'False').lower() in ('true', '1', 't')
It allows: things like true, True, TRUE, 1, "1", TrUe, t, T, ...
Update: After I read the commentary of Klaas, I updated the original code my_env = bool(os.getenv(... to my_env = os.getenv(... because in will result in a bool type
UPDATE:
After the @MattG commentary, I added a new solution that raises an error for entries like ttrue instead of returning False:
# ...
import os
# ...
TRUTHY_VALUES = ('true', '1', 't') # Add more entries if you want, like: `y`, `yes`, `on`, ...
FALSY_VALUES = ('false', '0', 'f') # Add more entries if you want, like: `n`, `no`, `off`, ...
VALID_VALUES = TRUTHY_VALUES + FALSY_VALUES
def get_bool_env_variable(name: str, default_value: bool | None = None) -> bool:
value = os.getenv(name) or default_value
if value is None:
raise ValueError(f'Environment variable "{name}" is not set!')
value = str(value).lower()
if value not in VALID_VALUES:
raise ValueError(f'Invalid value "{value}" for environment variable "{name}"!')
return value in TRUTHY_VALUES
# ...
my_env1 = get_bool_env_variable('ENV_VAR1') # Raise error if variable was not set
my_env2 = get_bool_env_variable('ENV_VAR2', default_value=False) # return False if variable was not set
['true', '1'] other options, like: ['true', '1', 'yes', 'y', 't']bool in the above example is superfluous... a in b is always a boolean anywayvalue in true_ must be changed to value.lower() in true_.All the same, but thats the most readable version for me:
DEBUG = (os.getenv('DEBUG', 'False') == 'True')
Here anything but True will evaluate to False. DEBUG is False unless explicitly set to True in ENV
I recommend using strtobool function
example:
DEBUG = strtobool(os.getenv("DEBUG", "false"))
You can check them in python documentation https://docs.python.org/3/distutils/apiref.html#distutils.util.strtobool
Only one problem, they raise an error if you pass the wrong value
Code
from distutils.util import strtobool
print("Value: ", strtobool("false"))
print("Value: ", strtobool("Wrong value"))
Output
Value: 0
Traceback (most recent call last):
File "<string>", line 9, in <module>
File "/usr/lib/python3.8/distutils/util.py", line 319, in strtobool
raise ValueError("invalid truth value %r" % (val,))
ValueError: invalid truth value 'wrong value'
Note: The entire distutils package has been deprecated and will be removed in Python 3.12Neither of the ways you have will work. os.environ['ENV_VAR'] alone will cause a KeyError if the key doesn't exist, and will return the value associated with the 'ENV_VAR' if it does. In either case, you'll error out, or compare to True or "true" which will always result in False (unless the value associated with the environment variable happens to be "true"; but that isn't what you're after).
To check if a mapping contains a particular key, you would use in:
if 'ENV_VAR' in os.environ:
# It contains the key
else:
# It doesn't contain the key
I use the following to have more strict typing and support wider boolean variations in inputs
import os
def getenv_bool(name: str, default: bool = False) -> bool:
return os.getenv(name, str(default)).lower() in ("yes", "y", "true", "1", "t")
Usage :
feature_1=getenv_bool('FEATURE_1', False)
Another alternative that accepts either "false", "False", "true" or "True":
import os
import ast
def getenv_bool(name: str, default: str = "False"):
raw = os.getenv(name, default).title()
return ast.literal_eval(raw)
ast.literal_eval will give surprising and confusing (for the user) error messages such as SyntaxError and IndentationError with deep stack traces for bad inputs.If you don't want to use the environs library mentioned above then strtobool is perfect for this. The only problem is it is deprecated, there does not seem to be a replacement library anywhere, but luckily it is only a few lines of simple code with no dependencies. Just implement the code:
# Copied from distutils.util.strtobool, which is deprecated
def strtobool (val):
"""Convert a string representation of truth to true (1) or false (0).
True values are case insensitive 'y', 'yes', 't', 'true', 'on', and '1'.
false values are case insensitive 'n', 'no', 'f', 'false', 'off', and '0'.
Raises ValueError if 'val' is anything else.
"""
val = val.lower()
if val in ('y', 'yes', 't', 'true', 'on', '1'):
return 1
elif val in ('n', 'no', 'f', 'false', 'off', '0'):
return 0
else:
raise ValueError("invalid truth value %r" % (val,))
Use it like this:
my_env_var_value = strtobool(os.getenv("ENV_VAR", "False"))
And YES, this will throw an error if the environment variable has some value that is neither true nor false. In the great majority of cases that is probably the best course of action.
Another possible solution is parse values as JSON values:
import json
import os
def getenv(name, default="null"):
try:
return json.loads(os.getenv(name, default))
except json.JSONDecodeError:
return name
The try is for cases when is not possible a direct conversion.
assert getenv("0") == 0
assert getenv("1.1") = 1.1
assert getenv("true") == True
assert getenv("Hello") = "Hello"
assert getenv('["list", "of", "strings"]') == ["list", "of", "strings"]
Here's my 2 cents: Why not use YAML?
Code:
import os, yaml
bool(yaml.load(os.getenv("MY_VAR") or "", yaml.Loader))
Test:
for val, expected in {
"yes": True,
"no": False,
"on": True,
"off": False,
"true": True,
"false": False,
"1": True,
"0": False,
"": False,
None: False,
}.items():
actual = bool(yaml.load(val or "", yaml.Loader))
assert actual == expected
I prefer to require strictly that the environment variable is set to either True or False, and to not allow so many other squishy possibilities. Also, if the variable isn't defined, I want an exception to be raised.
assert os.environ["MY_KEY"] in ("True", "False")
my_key = os.environ["MY_KEY"] == "True"
This will raise a KeyError if MY_KEY is not defined, or raise an AssertionError if it's not set to either 'True' or 'False'.
If you are doing this frequently and therefore want a function, use this:
def get_env_bool(key):
""" Handles the case of a boolean environment variable
"""
if not key in os.environ:
raise KeyError(f"No environment variable {key}")
if not os.environ[key] in ("True", "False"):
raise AssertionError(f"Key {key} is not proper boolean: {os.environ[key]}")
return os.environ[key] == "True"
Usage:
if get_env_bool("MY_KEY"):
...
Python Version: 3.9.13 (main, May 27 2022, 17:01:00)
I used solution below and it works perfect;
In your env file;
SOMEHING_ENABLED=True
and use case in your python file;
from distutils.util import strtobool
if bool(strtobool(os.getenv('SOMEHING_ENABLED'))):
# good to go.
Not: distutils will no longer work from version 3.12
In Django, if you are using python-dotenv also make sure you don't use DEBUG in the .env file as it will always default to True when we do os.getenv("DEBUG"). Use another variable e.g DEBUG_MODE. For example:
#.env
DEBUG_MODE = False
#settings.py
import os
from dotenv import load_dotenv
load_dotenv()
DEBUG = os.getenv("DEBUG_MODE", False) == "True"
.env, you need to load it. Get path: dotenv_path = os.path.join(BASE_DIR, ".env"). Load: load_dotenv(dotenv_path). Then, you can use DEBUG in the .env file.The way I see it - why not use the builtin bool() which is similar to for instance str()
import os
my_boolean_env_var = bool(os.getenv("MY_ENV_VAR"))
os.environ.get('ADT_email_send',str(False))=='True'