In a bunch of our projects, there's a DEBUG setting that's a boolean. Here's a gotcha, and corresponding good-practice for settings like this...
I'll set an environmental variable to false:
birkin@birkinbox-2021 ~ %
birkin@birkinbox-2021 ~ % export FOO="false"
birkin@birkinbox-2021 ~ %
birkin@birkinbox-2021 ~ % env | sort
FOO=false
[snip]...and then I'll load that in python:
>>>
>>> import os
>>>
>>> DEBUG = os.environ['FOO']
>>>
>>> DEBUG
'false'
>>> Ok, at a quick glance, everything seems good. But... there's a common, reasonable, pythonic way of coding that anyone expecting a boolean might use:
>>>
>>> if DEBUG:
... print( "I'm reasonably assuming the value is True" )
... else:
... print( "I'm reasonably assuming the value is False" )
...
I'm reasonably assuming the value is True
>>> Whoa! NOT what we want! This happens because that if statement is a general check for the existence of the "foo_setting" value. So if the value were the integer 0, or the empty string '', or the boolean False, it would have printed out "I'm reasonably assuming the value is False".
But the load of the envar is perceived as the string "false", not as the boolean False. Thus bad things could happen.
(If the envar would have been set to "False" it would have loaded as a boolean. But solutions that depend upon humans always doing the right thing aren't great solutions.)
Consequences of this mistaken settings-load could be avoided with code like:
>>>
>>> if DEBUG == True:
... print( "I'm reasonably assuming the value is True" )
... else:
... print( "I'm reasonably assuming the value is False" )
...
I'm reasonably assuming the value is False
>>> ...But that explicit check would have to be done in all places. A better way is to ensure you're dealing with expected values right up-front, when the envar is loaded.
I've long loaded the DEBUG setting like this:
>>> DEBUG = json.loads( os.environ['FOO'] )...which will throw an error on any non-numeric or non-json-boolean string. (json can load string values, but the syntax for setting a string value in an envar isn't likely to be done accidentally.) Another possibility that'd work even for numerals:
>>> DEBUG = os.environ['FOO']
>>> assert type(DEBUG) == bool