2

I want to decide project's status (production/development) by checking if there is a PRODUCTION environment variable.

The problem is that, surprisingly, this code returns True when there is no PRODUCTION environment variable:

PRODUCTION = True if os.getenv('PRODUCTION', False) in [0,"0"] else False # !!! In Bash, 0 means true and 1 false

The thing is that False in [0,"0"] gives True which I didn't know until now. I know that if 0 is the same as if False but this surprised me.

How to make it work and why it behaves like that?

EDIT

Solved this way but I'm still curious why the "in" statement works like that.

PRODUCTION = True if str(os.getenv('PRODUCTION', 1)) == "0" else False # !!! In Bash, 0 means true and 1 false
Milano
  • 18,048
  • 37
  • 153
  • 353
  • I think `in` is basically doing `==` comparisons (note that `False == 0` evaluates `True`) - you can get a similar thing if comparing between integers and (integer-valued) floats. – alani Jun 16 '21 at 18:06
  • 1
    Can you please clarify what confuses you about the in operator? You seem to already know that False is equal to 0. So `False in [0,...]` because there is an element equal to False in the list. – MisterMiyagi Jun 16 '21 at 18:08
  • Asked differently, what do you think the in operator is doing, and why do you think this means you "should" get a different result? – MisterMiyagi Jun 16 '21 at 18:12
  • You're both right.. it does make sense.. thanks – Milano Jun 16 '21 at 18:13

1 Answers1

0

As you're reading from the environmental dict with .get(), you could instead index it and let it raise KeyError

try:
    prod = bool(os.environ["PRODUCTION"] == PROD_FLAG)
except KeyError:  # PRODUCTION not in env dict
    prod = False

If you're really interested in forms of "false", stringify 'em

if "false" in [str(x).lower() for x in iterable]

The problem with your initial solution is that 0 is equal to False in Python, which is not immediately obvious

>>> False == 0
True
>>> False in [0]
True
>>> False is 0
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
False

see also Falsey-ness which can bite you too What is Truthy and Falsy? How is it different from True and False?

ti7
  • 16,375
  • 6
  • 40
  • 68
  • This is *not* about falsy'ness. The empty list is falsy, but it is not in `[0, "0"]` and False is not in `[[], "0"]`. – MisterMiyagi Jun 16 '21 at 18:16
  • @MisterMiyagi their `.getenv()` solution compares each value in `[0, "0"]` to `False`, and they're surprised the first is non-obviously `True` – ti7 Jun 16 '21 at 18:17
  • Yes, and this is *not* due to falsy'ness. Most other falsy values will behave differently than 0 here. – MisterMiyagi Jun 16 '21 at 18:18
  • 1
    Oh, I see what you mean, indeed it's _equal_ to False (though not literally `is False` ..), rather than Falsey – ti7 Jun 16 '21 at 18:18