The only thing I can think of is that you were mistaken in that you set it but did not export it. That would explain why you could echo the value, but it didn't make into os.environ
in Python. Here's a demonstration:
>>> VAR1="vvv1"
>>> export VAR2="vvv2"
>>> echo $VAR1
vvv1
>>> echo $VAR2
vvv2
>>> python
Python 3.7.3 (default, Sep 16 2020, 12:18:14)
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> "VAR1" in os.environ
False
>>> "VAR2" in os.environ
True
So VAR1 was only set, but VAR2 was set and exported. Both can be echoed, but only the exported one shows up in Python.
To check at the command line for if a variable is set and exported, use export
and grep
:
>>> export | grep VAR1
>>> export | grep VAR2
declare -x VAR2="vvv2"
>>>
It's helpful to really understand what export
does. Only an exported variable will be inherited by child processes launched by the current shell process. So when you launch Python from the command line, that launches a child process. Only exported variables are copied into the child process, and so only exported variables are seen by Python.
It is this child process thing that explains why you can't run a shell script to set environment variables in your current shell. Because that script will run in a child process, it will only affect the variables in that child process. Once the script runs, that child process goes away. The main process's variable space was not affected by the script.
There is a way to run a script to set environment variables, and it can also be used to run a script that will have access to unexported variables. That is to run a script with '.' or 'source'. When you do . myscript.sh
or source myscript.sh
, this causes your script to be run in the current shell process. It prevents a subprocess from launching to run the script. So then the script is seeing and affecting the main shell environment.
Another small bit of trivia. I wasn't sure if there was any difference between . myscript.sh
and source myscript.sh
. Per this SO question, the only difference is portability. In Bash and other modern shells, there is no difference, but not all shells support both variants.