Why PYTHONPATH need to be exported?

56 Views Asked by At

I am getting some module not found excepiton when setting PYTHONPATH and then executing some py script :

$ PYTHONPATH=somepath/a/b
$ python myscript.py

Exception has occurred: ModuleNotFoundError       (note: full exception trace is shown but execution is paused at: _run_module_as_main)
No module named 'c'

but if I export PYTHONPATH, everything works fine

$ export PYTHONPATH=somepath/a/b
$ python myscript.py

==>ok

It is also working when I am inlining the PYTHONPATH assignation :

$ PYTHONPATH=somepath/a/b python myscript.py

==>ok

Why do we have this behavior ?

1

There are 1 best solutions below

3
dave_thompson_085 On

I'm amazed this doesn't seem to be a duplicate, but:

"Why ...?" -- because you're using a traditional (Bourne/Korn-family) shell on Unix or a Unix-alike such as WSL, although you don't identify which in your Q. This is the type of shell required by POSIX, and often described as such. Other Unixy shells like csh-family or fish are different and so are Windows command processors, although those do have some way to set environment variables.

In a POSIX shell, each variable has an attribute to select whether it is 'exported', that is, passed as an environment variable (an OS feature) when running as a child process a program such as python (or a script).

Any of the following commands or sequences (possibly separated by other unrelated commands) sets a variable as 'exported':

export foo=bar
export foo; foo=bar
foo=bar; export foo
typeset -x foo=bar
typeset -x foo; foo=bar
foo=bar; typeset -x foo
# in many Bourne/Korn shells declare is another name for typeset

IF the shell option -a is set, a simple assignment foo=bar also sets the export attribute.

These settings are 'permanent'; the exported variables are passed to all programs (and scripts) run subsequently, unless and until explicitly unset or changed or the shell exits.

In addition, a 'word' foo=bar at the beginning of a simple-command, prior to the word which specifies the program to be run, adds or replaces an environment variable for that command/process only -- unless the command is shell builtin, in which case the POSIX behavior is unspecified and actual shells may vary.

But an assignment foo=bar by itself -- not as a prefix to a simple-command and not preceded or followed by setting the export attribute and without option -a in effect -- only sets a shell variable which is NOT 'exported' so it is not passed to or seen by a child process such as python.