踩坑问题
在一次脚本的开发中,我希望设置一下环境变量的值。
因为实习公司给的是Windows做开发机,所以环境变量的值要用set来改变,而不是Linux里的export。
关于set的基本使用这里不过多赘述,windows已经讲得很清楚了,大家可以通过命令行输入 set /?来查看说明。
这里用一个测试来说明我的问题。
-
首先先新建一个环境变量。
-
在命令行使用
set testVar
来查看变量的值。 -
然后通过
set testVar = false
来改变变量的值,再打印看一下。 -
感觉没问题,然后在python脚本里尝试:
-
import os def function(): cmd = "set testVar" os.system(cmd) setCmd = cmd + "=false" print(setCmd) system = os.system(setCmd) print(system) os.system(cmd) function()
-
运行结果:
-
出问题了,明明中间执行了
set testVar=false
,为什么最后testVar
的值还是true?
测试
在发现问题后,我又进行了各种测试,然后发现一个现象。当我在命令行修改了testVar
的值之后,环境变量中的值其实并未被修改。
或者说,在一个命令行里修改了testVar
的值,再重新开一个命令行输出testVar
的值,还是修改前的值。
也就是说,set并没有对真正的环境变量的值进行改变,而是只对当前命令行改变生效了。
在仔细阅读一下set /?, 其实第一句话就点出来了
所以其实set的修改范围仅仅对当前cmd
有效。
os.system
虽然说set修改范围有限,但是在脚本里我是在同一个进程下执行的,为什么值也没被改变呢?
在阅读一些文章后发现,os.system的原理是创建一个子进程在系统上执行命令。所以说,多次的os.system之间是互不影响的。
在linux上也会有这样的问题:
os.system("cd /user/local")
os.mkdir("aaa.txt")
上述命令并不会在/user/local目录下创建文件,而是在当前目录下创建aaa.txt.
所以一切就能解释通了。
上面的代码就可以改为:
os.system("cd /user/local && mkdir aaa.txt")
就可以实现在/user/local目录下创建文件了。
Linux上修改环境变量
Linux上修改环境变量的指令是export.
为了知道Linux上和Windows上有没有区别,特意去找了一台Mac来尝试。
执行脚本
import os
def function():
cmd = "export testVar=true"
os.system(cmd)
echo = "echo $testVar"
os.system(echo)
cmd = "export testVar=false"
os.system(cmd)
os.system(echo)
function()
结果什么都没输出。
然后在命令行尝试:
export testVar=true
echo $testVar
能正常输出true。
export testVar=true
echo $testVar
也能正常输出false。
再重新开一个终端命令行
echo $testVar
什么都没输出。
所以最终的结论是:export的有效范围也仅限于本次终端命令。新启动一个终端命令行,export的修改就失效了。
结合os.system()的原理,也就能解释为什么脚本没有输出任何东西了。
总结
-
Windows下利用set修改、设置环境变量仅对当前的cmd.exe有效,不会影响到别的cmd.exe。
-
Linux下export的有效范围也仅限于当前终端命令行。
-
python里os.system()原理是创建一个子进程执行系统命令,多个os.system()互不影响。
参考: