os.getenv doesn't work as default value for a function parameter if set within python

Viewed 1762

With the following code, I'd expect func1 to print the host value (5000) I set twice.

import os

def func1(host = os.getenv("HOST")):
    print(host)
    print(os.getenv("HOST"))

os.environ["HOST"] = "5000"
func1()

Output:

None
5000

Strange. Let's check the whole list of env vars.

def func2(env = os.environ):
    print(env)

os.environ["HOST"] = "5000"
func2()

Output:

environ({..., 'Host': '5000'})

Okay, very strange, so can I grab it using environ?

def func3(host = os.environ["HOST"]):
    print(host)

os.environ["HOST"] = "5000"
func3()

Output:

Traceback (most recent call last):
  File "mytest.py", line 10, in <module>
    def func3(host = os.environ["HOST"]):
  File "/Users/me/.pyenv/versions/3.7.3/lib/python3.7/os.py", line 678, in __getitem__
    raise KeyError(key) from None
KeyError: 'HOST'

Am I missing something, or this this a bug with python?

2 Answers

I believe the default values are set at runtime not when the function is called. So if you were to set the environment variable above the function declaration it would work.

import os

os.environ["test"] = "test"

def foo(bar=os.environ["test"]):
     print(bar)
     print(os.environ["test"])

foo()

Output:

test
test

Function default values are evaluated when the function is defined. If you add a line to your script

import os


print(os.getenv("HOST"))


def func1(host = os.getenv("HOST")):
    print(host)
    print(os.getenv("HOST"))


os.environ["HOST"] = "5000"
func1()

you'll get a preview of what the default value of the host parameter will be. It's the value of HOST as inherited from the parent process, or None if HOST isn't currently in the environment at all.

Related