It is my understanding that both are supposed to set environmental variables. But toggling between these two in django's manage.py
file leads to different outcomes.
>>> help(os.environ.putenv)
putenv(name, value, /)
Change or add an environment variable
If I edit the manage.py
file and change os.environ.setdefault
to os.environ.putenv
, I get the following:
Question: Why does os.environ.setdefault
work in this case, but os.environ.putenv
does not work.
The main difference is that os.environ.setdefault
treats os.environ
as a python dict
, while os.putenv
or os.environ.putenv
makes changes to the environment that affect subprocesses started with os.system()
, os.popen()
or os.fork()
and os.execv()
. The documentation for os.putenv
notes the following about the relationship between os.environ
and os.putenv
:
Assignments to items in
os.environ
are automatically translated into corresponding calls to putenv(); however, calls toputenv()
don’t updateos.environ
, so it is actually preferable to assign to items of os.environ.
Based on the above statement, updating the environment variables with os.putenv
does not necessarily update the os.environ
dictionary. Therefore, it comes down to how the environment variable in question is used. In the case of Django
, the environment variable in question is accessed in the django/config/__init__.py
file with the following line of code:
settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
Clearly, this line is treating os.environ
as a dictionary. Since changes made using os.putenv
don't affect this os.environ
dictionary, django
is not able to find the settings module (i.e. the settings_module
variable is equal to None
).
In sum, if you want to update environment variables, it's more encompassing to use os.environ['VARIABLE'] = 'VALUE'
or os.environ.setdefault
. Because, as mentioned above, updating the os.environ
both updates the dictionary and also calls os.putenv
.