python - 从 Python 修改 Windows 环境变量的接口(interface)

标签 python windows environment-variables

如何通过 Python 脚本持续修改 Windows 环境变量? (这是 setup.py 脚本)

我正在寻找用于此的标准功能或模块。我已经熟悉 registry way of doing it ,但也欢迎对此发表任何评论。

最佳答案

使用 setx 有一些缺点,特别是如果您尝试附加到环境变量(例如 setx PATH %Path%;C:\mypath),这将在您每次运行时重复附加到路径,这可能是一个问题。更糟糕的是,它不区分机器路径(存储在 HKEY_LOCAL_MACHINE)和用户路径(存储在 HKEY_CURRENT_USER)。您在命令提示符处看到的环境变量由这两个值的串联组成。因此,在调用 setx 之前:

user PATH == u
machine PATH == m
%PATH% == m;u

> setx PATH %PATH%;new

Calling setx sets the USER path by default, hence now:
user PATH == m;u;new
machine PATH == m
%PATH% == m;m;u;new

每次调用 setx 附加到 PATH 时,系统路径不可避免地会在 %PATH% 环境变量中重复。这些更改是永久性的,不会因重新启动而重置,因此会在机器的整个生命周期内累积。

试图在 DOS 中弥补这一点超出了我的能力范围。所以我转向了 Python。我今天想出的解决方案,通过调整注册表来设置环境变量,包括附加到PATH而不引入重复,如下:

from os import system, environ
import win32con
from win32gui import SendMessage
from _winreg import (
    CloseKey, OpenKey, QueryValueEx, SetValueEx,
    HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE,
    KEY_ALL_ACCESS, KEY_READ, REG_EXPAND_SZ, REG_SZ
)

def env_keys(user=True):
    if user:
        root = HKEY_CURRENT_USER
        subkey = 'Environment'
    else:
        root = HKEY_LOCAL_MACHINE
        subkey = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
    return root, subkey


def get_env(name, user=True):
    root, subkey = env_keys(user)
    key = OpenKey(root, subkey, 0, KEY_READ)
    try:
        value, _ = QueryValueEx(key, name)
    except WindowsError:
        return ''
    return value


def set_env(name, value):
    key = OpenKey(HKEY_CURRENT_USER, 'Environment', 0, KEY_ALL_ACCESS)
    SetValueEx(key, name, 0, REG_EXPAND_SZ, value)
    CloseKey(key)
    SendMessage(
        win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')


def remove(paths, value):
    while value in paths:
        paths.remove(value)


def unique(paths):
    unique = []
    for value in paths:
        if value not in unique:
            unique.append(value)
    return unique


def prepend_env(name, values):
    for value in values:
        paths = get_env(name).split(';')
        remove(paths, '')
        paths = unique(paths)
        remove(paths, value)
        paths.insert(0, value)
        set_env(name, ';'.join(paths))


def prepend_env_pathext(values):
    prepend_env('PathExt_User', values)
    pathext = ';'.join([
        get_env('PathExt_User'),
        get_env('PathExt', user=False)
    ])
    set_env('PathExt', pathext)



set_env('Home', '%HomeDrive%%HomePath%')
set_env('Docs', '%HomeDrive%%HomePath%\docs')
set_env('Prompt', '$P$_$G$S')

prepend_env('Path', [
    r'%SystemDrive%\cygwin\bin', # Add cygwin binaries to path
    r'%HomeDrive%%HomePath%\bin', # shortcuts and 'pass-through' bat files
    r'%HomeDrive%%HomePath%\docs\bin\mswin', # copies of standalone executables
])

# allow running of these filetypes without having to type the extension
prepend_env_pathext(['.lnk', '.exe.lnk', '.py'])

不影响当前进程或父shell,但会影响运行后打开的所有cmd窗口,无需重启,可以安全地多次编辑重新运行,不会引入任何重复。

关于python - 从 Python 修改 Windows 环境变量的接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1085852/

相关文章:

Python:向文件添加内容而不删除其旧内容

python - 具有内置输入函数的类方法(Python)

python - 求解最大权重二分 b 匹配

powershell修改 '.\'并调用.ps1

python - 具有动态属性的 Django 模型

Windows Powershell 输出到文件。奇怪的角色

python - 删除和列出超过字符限制的目录

c - Linux 的 Windows 子系统上的 CTRL+D 问题

bash - 在 (Git)bash 中,在 key 中设置具有特殊字符的环境变量

javascript - process.env.VARIABLE 在分配字符串后将变为未定义