一、os.environ
Python对环境变量的读取是非常方便的,os.environ 是一个用以存储环境变量的字典类变量,读写都如同普通字典类变量一般无二
# read
print(os.environ["Path"])
# write
os.environ["Path"] = ""
特点:
① 引用类型变量的值是真值
假如系统环境变量中存在以下两个变量
JAVA_HOME = "C:\Program Files\Java\jdk1.8.0_152"
Path = "C:\Program Files\Git\cmd;%JAVA_HOME%\bin;"
os.environ["Path"] 读取到的值是 "C:\Program Files\Git\cmd;C:\Program Files\Java\jdk1.8.0_152\bin;"
② os.environ 对环境变量的修改仅在当前Shell有效
当退出程序后,手动查询 “我的电脑 → 高级系统设置 → 环境变量 → 系统变量” 时发现变量值并没有真的被修改
参考资料
二、win32api
环境变量本质上是注册表项 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
的诸多子项
通过修改注册表键值即可完成修改 环境变量
参考资料
《Persistent Environment Variables on Windows》
三、管理员权限修改注册表
参考资料
《How to modify a REG_EXPAND_SZ value》
程序流程:
1、创建空文件 ..\tool\script\srv.reg
2、动态写入 注册表内容
3、subprocess.Popen 调用 srv.reg
# !/usr/bin/python3
# coding: utf-8
import os
import subprocess
import traceback
def modify(key, val):
assert (type(key) is str)
assert (type(val) is str)
key = str(key).strip()
val = hex2(format(val))
# 版本声明
cmd = 'Windows Registry Editor Version 5.00\n'
# 必须空行
cmd += '\n'
# 添加主键
cmd += '[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]\n'
# 添加键值
cmd += '"%s"=hex(2):%s\n' % (key, val)
reg(cmd)
def remove(key):
assert (type(key) is str)
# 版本声明
cmd = 'Windows Registry Editor Version 5.00\n'
# 必须空行
cmd += '\n'
# 添加主键
cmd += '[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]\n'
# 添加键值
cmd += '"%s"=-\n' % key
reg(cmd)
def batch(kvList):
assert (type(kvList) is list)
assert (len(kvList) > 0)
# 版本声明
cmd = 'Windows Registry Editor Version 5.00\n'
# 必须空行
cmd += '\n'
# 添加主键
cmd += '[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]\n'
for kv in kvList:
key = str(kv[0]).strip()
if len(key) < 1:
continue
val = str(kv[1]).strip()
val = hex2(format(val))
# 添加键值
cmd += '"%s"=hex(2):%s\n' % (key, val)
reg(cmd)
def hex2(val):
hexList = [hex(ord(c)).replace("0x", "") for c in val]
hexStr = ",00,".join(hexList)
hexStr += ",00"
return hexStr
def reg(cmd):
path = os.getcwd() + r"\tool\script\srv.reg"
f = None
try:
f = open(path, 'w')
f.write(cmd)
except Exception as e:
traceback.print_exc()
raise e
finally:
if f:
f.close()
command(path, 1800000)
def command(cmd, timeout=1800000):
try:
sp = subprocess.Popen(
cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
print("[PID] %s: %s" % (sp.pid, cmd))
sp.wait(timeout=timeout)
stderr = str(sp.stderr.read().decode("gbk")).strip()
stdout = str(sp.stdout.read().decode("gbk")).strip()
if "" != stderr:
raise Exception(stderr)
if stdout.find("失败") > -1:
raise Exception(stdout)
except Exception as e:
raise e
def format(path):
if path is None:
return ""
path = path.lstrip()
path = path.rstrip()
while path.find("/") >= 0:
path = path.replace("/", "\\")
while path.find("\\\\") >= 0:
path = path.replace("\\\\", "\\")
return path
以 JDK环境变量为例,共三个参数 JAVA_HOME、CLASSPATH、Path
JAVA_HOME = "C:\Program Files\Java\jdk1.8.0_152"
CLASSPATH = "."
Path += ";%JAVA_HOME%\bin;"
JDK环境变量配置主方法如下
# !/usr/bin/python3
# coding: utf-8
import copy
import os
import subprocess
import traceback
def cfgEnv(java_home, class_path, path_append):
# part1
valKeyDict = {}
valList = []
for key, val in os.environ.items():
if str(val).find(";") > -1:
continue
key = str(key).strip()
val = str(val).strip()
if val not in valKeyDict:
valKeyDict[val] = key
valList.append(val)
valList.sort(key=lambda obj: len(obj), reverse=False)
# part2
clazz = copy.deepcopy(os.environ["CLASSPATH"])
clazz += ";" + class_path
clazzList = list(set(clazz.split(";")))
clazzList.remove("")
for i in range(len(clazzList)):
v = clazzList[i]
for val in valList:
if v.startswith(val):
key = valKeyDict[val]
clazzList[i] = v.replace(val, "%" + key + "%")
clazzList.sort(key=lambda obj: len(obj), reverse=False)
clazz = ";".join(clazzList)
# part3
path = copy.deepcopy(os.environ["Path"])
path += ";" + path_append
pathList = list(set(path.split(";")))
pathList.remove("")
for i in range(len(pathList)):
v = pathList[i]
for val in valList:
if v.startswith(val):
key = valKeyDict[val]
pathList[i] = v.replace(val, "%" + key + "%")
pathList.sort(key=lambda obj: len(obj), reverse=False)
path = ";".join(pathList)
# part4
kvList = [
("JAVA_HOME", java_home),
("CLASSPATH", clazz),
("Path", path)
]
batch(kvList)