使用Python全局和永久修改`PATH`环境变量

时间:2011-10-27 10:14:22

标签: python cross-platform environment-variables distutils

是否可以使用Python(distutils)以独立于平台的方式全局和永久地修改PATH环境变量?

背景

我有一些应用程序(Serna XML Editor的插件),现在我要为它安装一个安装程序,可能使用python distutils(setup.py)。安装setup.py之后需要修改PATH环境变量以将安装目录添加到其值中。

实现我想要的可能解决方案是将可执行文件复制到/usr/local/bin或其他地方,但对于MS Windows,在哪里复制高级管理员并不明显。

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

据我所知,distutils没有用于永久更改环境变量的跨平台实用程序。因此,您必须编写特定于平台的代码。

在Windows中,环境变量存储在注册表中。这是一个示例代码,用于读取和设置其中的一些键。我只使用标准的库(不需要安装pywin32!)来实现它。

import _winreg as winreg
import ctypes

ENV_HTTP_PROXY = u'http://87.254.212.121:8080'


class Registry(object):
    def __init__(self, key_location, key_path):
        self.reg_key = winreg.OpenKey(key_location, key_path, 0, winreg.KEY_ALL_ACCESS)

    def set_key(self, name, value):
        try:
            _, reg_type = winreg.QueryValueEx(self.reg_key, name)
        except WindowsError:
            # If the value does not exists yet, we (guess) use a string as the
            # reg_type
            reg_type = winreg.REG_SZ
        winreg.SetValueEx(self.reg_key, name, 0, reg_type, value)

    def delete_key(self, name):
        try:
            winreg.DeleteValue(self.reg_key, name)
        except WindowsError:
            # Ignores if the key value doesn't exists
            pass



class EnvironmentVariables(Registry):
    """
    Configures the HTTP_PROXY environment variable, it's used by the PIP proxy
    """

    def __init__(self):
        super(EnvironmentVariables, self).__init__(winreg.HKEY_LOCAL_MACHINE,
                                                   r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment')

    def on(self):
        self.set_key('HTTP_PROXY', ENV_HTTP_PROXY)
        self.refresh()

    def off(self):
        self.delete_key('HTTP_PROXY')
        self.refresh()

    def refresh(self):
        HWND_BROADCAST = 0xFFFF
        WM_SETTINGCHANGE = 0x1A

        SMTO_ABORTIFHUNG = 0x0002

        result = ctypes.c_long()
        SendMessageTimeoutW = ctypes.windll.user32.SendMessageTimeoutW
        SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, 0, u'Environment', SMTO_ABORTIFHUNG, 5000, ctypes.byref(result));

这只是您开始使用的示例代码,它只实现设置和删除密钥。

确保在更改注册表后始终调用refresh方法。这将告诉Windows某些内容已更改,它将刷新注册表设置。

以下是我编写的完整应用程序的链接,它是Windows的代理切换器: https://bitbucket.org/canassa/switch-proxy/

答案 1 :(得分:0)

Distutils不设置环境变量。在Windows上,这意味着与注册表混淆;在UNIX上,它需要找到正确的shell配置文件(这不是一件容易的事)并对其进行编辑,这在这种文化中并没有完成:人们被告知编辑他们的$ PATH或者使用程序的完整路径。