khachik
khachik

Reputation: 28703

Modify `PATH` environment variable globally and permanently using Python

Is that possible to modify PATH environment variable, globally and permanently, in a platform-independent way using Python (distutils)?

Background

I have some application (a plugin for Serna XML Editor), and now I'm going to make an installer for it, probably using python distutils (setup.py). After the installation setup.py needs to modify the PATH environment variable to add the installation directory to its value.

A possible solution to achieve what I want would be to copy the executables to /usr/local/bin or somewhere else, but for MS Windows it is not obvious where to copy execs.

Any ideas?

Upvotes: 0

Views: 2465

Answers (2)

merwok
merwok

Reputation: 6907

Distutils doesn’t set environment variables. On Windows, this would imply mucking with the registry; on UNIX, it would require to find out the right shell configuration file (which is not trivial) and edit it, which is just not done in this culture: people are told to edit their $PATH or to use full paths to the programs.

Upvotes: 0

Cesar Canassa
Cesar Canassa

Reputation: 20163

As far as I know, distutils has no cross-platform utility for permanently changing environment variables. So you will have to write platform specific code.

In Windows, environment variables are stored in the registry. This is a sample code to read and set some of it's keys. I use only the standard librarie (no need to install pywin32!) to achieve that.

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

This is just a sample code for you to get started with, it only implements settings and deleting keys.

Make sure that you always calls the refresh method after changing a registry. This will tell Windows that something has changed and it will refresh the registry settings.

Here is the link for the full application that I wrote, its a proxy switcher for Windows: https://bitbucket.org/canassa/switch-proxy/

Upvotes: 3

Related Questions