首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用于从Python修改Windows环境变量的界面

用于从Python修改Windows环境变量的界面
EN

Stack Overflow用户
提问于 2009-07-06 07:48:41
回答 4查看 13.5K关注 0票数 19

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

我正在寻找一个标准函数或模块来实现这一点。我对registry way of doing it已经很熟悉了,但也欢迎对此发表任何意见。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-07-18 01:25:12

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

代码语言:javascript
复制
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,如下所示:

代码语言:javascript
复制
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窗口,不需要重新启动,并且可以安全地编辑和重新运行多次,而不会引入任何重复项。

票数 25
EN

Stack Overflow用户

发布于 2009-07-06 08:59:43

使用外部Windows setx命令可能也很简单:

代码语言:javascript
复制
C:\>set NEWVAR
Environment variable NEWVAR not defined

C:\>python
Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.system('setx NEWVAR newvalue')
0
>>> os.getenv('NEWVAR')
>>> ^Z


C:\>set NEWVAR
Environment variable NEWVAR not defined

现在打开一个新的命令提示符:

代码语言:javascript
复制
C:\>set NEWVAR
NEWVAR=newvalue

如您所见,setx既不为当前会话设置变量,也不为父进程(第一个命令提示符)设置变量。但它确实会在注册表中永久设置该变量,以供将来的进程使用。

我认为根本没有办法改变父进程的环境(如果有的话,我很想听听!)

票数 5
EN

Stack Overflow用户

发布于 2009-07-06 07:59:19

注册表的方式是如果你想永久地修改它,我猜这就是你想要的,因为它是在setup.py中。

暂时只针对您的进程,那么os.environ就是诀窍。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1085852

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档