Python实现环境变量持久化修改

一、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有效

当退出程序后,手动查询 “我的电脑 → 高级系统设置 → 环境变量 → 系统变量” 时发现变量值并没有真的被修改

 

参考资料

《os.environ and os.putenv》

 

二、win32api

环境变量本质上是注册表项 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment

的诸多子项

通过修改注册表键值即可完成修改 环境变量

参考资料

《Python修改注册表》

《Python winreg》

《Persistent Environment Variables on Windows》

 

三、管理员权限修改注册表

参考资料

《注册表REG文件编写大全》

《注册表文件修改、添加和删除项和子项的键值》

《注册表REG_SZ和REG_EXPAND_SZ的区别》

《Python字符串与16进制互转》

《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)

 

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值