Is there any difference at all between both approaches?
>>> os.getenv('TERM')
'xterm'
>>> os.environ.get('TERM')
'xterm'
>>> os.getenv('FOOBAR', "not found") == "not found"
True
>>> os.environ.get('FOOBAR', "not found") == "not found"
True
They seem to have the exact same functionality.
One difference observed (Python27):
os.environ
raises an exception if the environmental variable does not exist.
os.getenv
does not raise an exception, but returns None
See this related thread. Basically, os.environ
is found on import, and os.getenv
is a wrapper to os.environ.get
, at least in CPython.
EDIT: To respond to a comment, in CPython, os.getenv
is basically a shortcut to os.environ.get
; since os.environ
is loaded at import of os
, and only then, the same holds for
os.getenv
.
In Python 2.7 with iPython:
>>> import os
>>> os.getenv??
Signature: os.getenv(key, default=None)
Source:
def getenv(key, default=None):
"""Get an environment variable, return None if it doesn't exist.
The optional second argument can specify an alternate default."""
return environ.get(key, default)
File: ~/venv/lib/python2.7/os.py
Type: function
So we can conclude os.getenv
is just a simple wrapper around os.environ.get
.
While there is no functional difference between os.environ.get
and os.getenv
, there is a massive difference between os.putenv
and setting entries on os.environ
. os.putenv
is broken, so you should default to os.environ.get
simply to avoid the way os.getenv
encourages you to use os.putenv
for symmetry.
os.putenv
changes the actual OS-level environment variables, but in a way that doesn't show up through os.getenv
, os.environ
, or any other stdlib way of inspecting environment variables:
>>> import os
>>> os.environ['asdf'] = 'fdsa'
>>> os.environ['asdf']
'fdsa'
>>> os.putenv('aaaa', 'bbbb')
>>> os.getenv('aaaa')
>>> os.environ.get('aaaa')
You'd probably have to make a ctypes call to the C-level getenv
to see the real environment variables after calling os.putenv
. (Launching a shell subprocess and asking it for its environment variables might work too, if you're very careful about escaping and --norc
/--noprofile
/anything else you need to do to avoid startup configuration, but it seems a lot harder to get right.)
In addition to the answers above:
$ python3 -m timeit -s 'import os' 'os.environ.get("TERM_PROGRAM")'
200000 loops, best of 5: 1.65 usec per loop
$ python3 -m timeit -s 'import os' 'os.getenv("TERM_PROGRAM")'
200000 loops, best of 5: 1.83 usec per loop