从 Python 修改 Windows 环境变量的接口 [英] Interface for modifying Windows environment variables from Python

查看:35
本文介绍了从 Python 修改 Windows 环境变量的接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How can I persistently modify the Windows environment variables from a Python script? (it's the setup.py script)

我正在寻找用于此的标准功能或模块.我已经熟悉 注册方式,但任何关于此的评论也是欢迎.

I'm looking for a standard function or module to use for this. I'm already familiar with the registry way of doing it, but any comments regarding that are also welcome.

推荐答案

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

Using setx has few drawbacks, especially if you're trying to append to environment variables (eg. setx PATH %Path%;C:mypath) This will repeatedly append to the path every time you run it, which can be a problem. Worse, it doesn't distinguish between the machine path (stored in HKEY_LOCAL_MACHINE), and the user path, (stored in HKEY_CURRENT_USER). The environment variable you see at a command prompt is made up of a concatenation of these two values. Hence, before calling 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% 环境变量中重复.这些更改是永久性的,不会因重新启动而重置,因此会在机器的整个生命周期内累积.

The system path is unavoidably duplicated in the %PATH% environment variable every time you call setx to append to PATH. These changes are permanent, never reset by reboots, and so accumulate through the life of the machine.

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

Trying to compensate for this in DOS is beyond my ability. So I turned to Python. The solution I have come up with today, to set environment variables by tweaking the registry, including appending to PATH without introducing duplicates, is as follows:

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'SYSTEMCurrentControlSetControlSession ManagerEnvironment'
    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%cygwinin', # Add cygwin binaries to path
    r'%HomeDrive%%HomePath%in', # shortcuts and 'pass-through' bat files
    r'%HomeDrive%%HomePath%docsinmswin', # copies of standalone executables
])

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

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

It does not affect the current process or the parent shell, but it will affect all cmd windows opened after it is run, without needing a reboot, and can safely be edited and re-run many times without introducing any duplicates.

这篇关于从 Python 修改 Windows 环境变量的接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆