为什么需要导出PYTHONPATH?
我在设置PYTHONPATH后执行一些Python脚本时,遇到了“找不到模块”的错误:
$ 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'
但是如果我用export命令来设置PYTHONPATH,一切就正常了
$ export PYTHONPATH=somepath/a/b
$ python myscript.py
==>ok
当我直接在命令中设置PYTHONPATH时,它也能正常工作:
$ PYTHONPATH=somepath/a/b python myscript.py
==>ok
为什么会出现这种情况呢?
1 个回答
我很惊讶这个问题似乎不是重复的,但我来解释一下:
“为什么……?”——因为你在使用传统的Unix shell(比如Bourne或Korn系列),或者像WSL这样的Unix类系统,虽然你在问题中没有具体说明。这种类型的shell是POSIX所要求的,通常也被这样描述。其他Unix类的shell,比如csh系列或fish,都是不同的,Windows的命令处理器也不一样,虽然它们也有某种方式来设置环境变量。
在POSIX shell中,每个变量都有一个属性,用来选择它是否被“导出”,也就是说,当运行一个程序(比如python或脚本)作为子进程时,它会作为一个环境变量(操作系统的一个功能)被传递。
以下任意命令或命令组合(可能夹杂着其他无关的命令)都可以将一个变量设置为“导出”:
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
如果 shell选项-a
被设置,那么简单的赋值foo=bar
也会设置导出属性。
这些设置是“永久”的;导出的变量会被传递给之后运行的所有程序(和脚本),除非明确取消设置、改变,或者shell退出。
此外,在一个简单命令的开头,使用foo=bar
这个“词”,在指定要运行的程序之前,只会为那个命令/进程添加或替换一个环境变量仅仅是——除非这个命令是shell内置的,在这种情况下,POSIX的行为就不确定了,实际的shell可能会有所不同。
但是,单独的赋值foo=bar
——不是作为简单命令的前缀,也没有设置导出属性,且没有-a
选项生效——只会设置一个shell变量,这个变量并没有被“导出”,所以它不会被传递给子进程,比如python,也看不到。