什么是环境变量
用户变量仅对当前用户有效,系统变量对整个系统有效
环境变量就是一个字符串,为了方便修改给隔开了(图形化界面)
环境变量可以用来配置路径,也可以用来配置其他,比如图中的 NUMBER_OF_PROCESSORS,指明了系统中处理器核心是12个。
!!!环境变量不仅只有路径,还可以提供其它信息
怎么产生的
一部分是由程序、系统创建、修改 的,
一部分是由人手工创建的。
程序可以通过操作系统编程接口 增加、读取、删除、修改 环境变量配置。
人也可以通过命令或者操作界面 增加、查看、删除、修改 环境变量配置。
有什么用
环境变量本身只是一些配置信息。
主要是为应用程序提供信息, 程序可以根据这些信息,决定它们的行为。
因为某些程序会读取一些环境变量的值,根据这些值决定程序的处理。
举个例子,上文中的 NUMBER_OF_PROCESSORS,是操作系统程序创建的,目的就是提供信息给 系统中所有的程序, 告诉他们当前系统所在计算机的CPU核心是4个。
那么如果有一个程序需要给客户显示系统中有多少个CPU,就可以读取这个数据,显示在界面上。
更常见的,就是指明一些程序文件或者数据文件所在的目录。比如 path、ANDROID_HOME 。
TMP 临时目录 有些程序会有一些临时文件,就可以通过环境变量获取TMP临时目录的路径,放进去
从上面的描述,可以思考出这样一个结论:
到底哪些程序 会 受哪些环境变量的影响, 是由程序本身决定的(环境变量再全,程序用不着,那环境变量也不会影响到程序)。
程序的代码 到底会 读取哪些环境变量,根据这些值做出什么行为,完全是程序开发者设计决定的。
path环境变量
命令行解释器(运行在命令行窗口中的)/ shell程序 / 解释执行我们从 命令行窗口(术语是伪终端模拟器)输入命令的程序。
当我们在命令行窗口敲入如下一行指令的时候
python.exe hyhy.py
shell程序会接收到这行命令, 它会以空格作为分隔符,把指令分割为n个部分,第一个部分就是要执行的程序,后面的都是这个程序的参数。
那么第一个问题就是, 到哪里找这个程序 python.exe 呢?
这就是根据环境变量 path 的值决定的。
它会依次到环境变量 path 里面指定的目录下面, 一个个的找。
先在哪个目录下面找到了python.exe,就执行哪个目录下面的 python.exe
看到这个例子,有些朋友可能又有误解了。
认为只要是配置目录的,都像 path 那样,可以配置好几个目录给程序依次查找。
不是的!!
还是那句话,怎么使用 环境变量 要看 各个程序本身的设计。
比如 环境变量 ANDROID_HOME, 就是只能包含一个目录的。
修改环境变量配置
如果要使修改生效,必须重启cmd程序。
程序重启后,系统配置里面的环境变量就会生效。
加上环境变量,点击两个确定(把有关环境变量的两个窗口关掉),然后重启CMD/(或是别的程序)
因为,程序启动后,都会copy一份自己的环境变量,在程序运行期间修改的环境变量不会对已经启动的cmd或其它程序起作用。
补充:查看环境变量: echo %path%
进入到D盘:d:
环境变量的继承
其实,每个程序启动后(运行的程序叫做进程),就会自己拷贝 一份 父进程 环境变量表,作为该 进程 的环境变量表。
父进程 通俗的说 就是 启动了这个程序的 程序。
我们是在 Pycharm 里面运行 Python 程序, Pycharm 就是 Python 程序的父进程。
如果我们在 命令行cmd 中运行 Python 程序, 命令行cmd 就是 Python 程序的父进程。
那怎么解决这个问题呢?
连 Pycharm 也重新启动一下,这样 Pycharm 的 环境变量也更新了,它的子进程当然也会使用更新后的环境变量 就可以了。
那 pycharm 和 cmd 的父进程又是谁呢? 是 Windows 桌面管理器 explorer 。
explorer启动时,会从注册表中读取 环境变量配置作为自己进程的环境变量。
后续用户启动的程序 大都是 直接 或者 间接的从 explorer继承的环境变量,当然也就使用了配置的环境变量。
前面的例子,我们重启 cmd窗口,可以有效的重新加载系统配置的环境变量,是因为 cmd窗口的父进程是 explorer。
explorer每次启动新的进程,会重新读取配置环境变量, 作为子进程的环境变量。所以重启cmd就有效了。
但是 cmd 或者 pycharm 启动子进程, 并不会 重新读取 配置环境变量,而是把自己的环境变量作为 子进程的环境变量。 当然,修改的配置不会生效。
【例子】
#代码文件 e1.py
import os,subprocess
def printEnv(filename):
with open(filename,'w')as f:
for k,v in os.environ.items():
f.write(f'{k}:{v}\n')
#print(f'{k}:{v}\n')
#添加环境变量
os.environ['A1']='0077'
#执行将环境变量写入本地文件的函数
printEnv('e1.txt')
#运行另e2.py文件
subprocess.Popen(
[r'E:\1.Tool\0.Miniconda3\python.exe',r'D:\0.自主学习\Python基础\乱七八糟的知识点\4、环境变量\e2.py'],
shell=False
)
# 代码文件 e2.py
import os
def printEnv(filename):
with open(filename,'w') as f:
for k, v in os.environ.items():
f.write(f'{k}:{v}\n')
print(f'{k}:{v}\n')
os.environ['A2'] = '00772'
printEnv('e2.txt')
运行 e1.py 后, e1.py的代码会启动 e2.py。
所以程序运行时, e1.py 就是 e2.py 的父进程。
上面的程序运行后,可以发现 e2.py记录的 环境变量 是在 e1.py的基础上多一个 A2=白月黑羽2 。
可以证明:环境变量从父进程继承而来。
我的理解是:e1添加了一个环境变量给父进程(添加进了VSCode但是没有放到注册表里),之后调用e2,由于e2的环境变量是继承于(copy)父进程的,且e1是添加了环境变量之后才启动的e2,所以e2启动时会从父进程copy一份环境变量,所以print e2的env会有e1添加进去的环境变量。