why reading from environment variable in method argument gives None or default value in python. Environment variable is set before the call

Viewed 622

**Although the name is set in environment variable , it prints the default value **

import os

def test(name: str = os.environ.get('name_config', "dns")):

    print("function env is:", os.getenv('name_config'))
    print("name is ::", name)

if __name__ == "__main__":

    os.environ['name_config']= "john"
    print("env is:", os.getenv('name_config'))
    #print(os.environ)
    test()
    test("test-name")

~ ~

2 Answers

The results I'm getting make perfect sense:

env is: john
function env is: john
name is :: dns
function env is: john
name is :: test-name

The first line is printed by:

print("env is:", os.getenv('name_config'))

This makes sense because you just set it to 'john' on the previous line.

The second line is printed by:

    print("function env is:", os.getenv('name_config'))

Also makes sense, for the same reason - that's still that value, as it gets called later and the environment variable is not changed.

The third line is printed by:

    print("name is ::", name)

This prints the value of name, which is the parameter of the function, which was called as:

    test()

Since you didn't provide a value, name will have its default value, which is given as:

def test(name: str = os.environ.get('name_config', "dns")):

So, it would be os.environ.get('name_config', "dns") at the time the function was defined. This is before you changed it to 'john' and apparently there was no name_config variable, so you get the default value instead.

This is probably the main one that has you confused, and like others have said as well, the key thing is that the values in the def statement get evaluated when the def is first executed (i.e. the function is defined), not when the function is called.

The fourth line is printed by:

    print("function env is:", os.getenv('name_config'))

After the second call to this function:

    test("test-name")

Since you're just getting the environment variable again, it's still 'john' at this point.

Finally, the fifth line is printed by:

    print("name is ::", name)

This is part of that same call, but since you now provided an explicit value for name, namely 'test-name', that gets printed.

So, all makes sense?

The default value for an argument is evaluated when the function is defined. Since os.environ['name_config']= "john" isn't evaluated until after def test(name: str = os.environ.get('name_config', "dns")): has run, and locked in the value prior to your modification, the effect of it isn't seen. If you want this to work, defer resolution of the default until the function is actually run, e.g.:

def test(name: str = ""):  # "" is just an arbitrary string value we assume the user wouldn't use
    if not name:
        name = os.environ.get('name_config', 'dns')
    print("function env is:", os.getenv('name_config'))
    print("name is ::", name)
Related