Here's something that does what you want which is similar to code in the jaraco.windows project. And like it, only uses built-in Python modules—so doesn't require first downloading and installing the pywin32 extensions. Plus it's Python 2.6+ and 3.x compatible and supports Unicode environment variables and values (directory paths in this case).
Note that Windows administrator rights are required to change the permanent system-level environment variables.
import ctypes
from ctypes.wintypes import HWND, UINT, WPARAM, LPARAM, LPVOID
LRESULT = LPARAM # synonymous
import os
import sys
try:
import winreg
unicode = str
except ImportError:
import _winreg as winreg # Python 2.x
class Environment(object):
path = r'SYSTEMCurrentControlSetControlSession ManagerEnvironment'
hklm = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
key = winreg.OpenKey(hklm, path, 0, winreg.KEY_READ | winreg.KEY_WRITE)
SendMessage = ctypes.windll.user32.SendMessageW
SendMessage.argtypes = HWND, UINT, WPARAM, LPVOID
SendMessage.restype = LRESULT
HWND_BROADCAST = 0xFFFF
WM_SETTINGCHANGE = 0x1A
NO_DEFAULT_PROVIDED = object()
def get(self, name, default=NO_DEFAULT_PROVIDED):
try:
value = winreg.QueryValueEx(self.key, name)[0]
except WindowsError:
if default is self.NO_DEFAULT_PROVIDED:
raise ValueError("No such registry key", name)
value = default
return value
def set(self, name, value):
if value:
winreg.SetValueEx(self.key, name, 0, winreg.REG_EXPAND_SZ, value)
else:
winreg.DeleteValue(self.key, name)
self.notify()
def notify(self):
self.SendMessage(self.HWND_BROADCAST, self.WM_SETTINGCHANGE, 0, u'Environment')
Environment = Environment() # singletion - create instance
PATH_VAR = 'PATH'
def append_path_envvar(addpath):
def canonical(path):
path = unicode(path.upper().rstrip(os.sep))
return winreg.ExpandEnvironmentStrings(path) # Requires Python 2.6+
canpath = canonical(addpath)
curpath = Environment.get(PATH_VAR, '')
if not any(canpath == subpath
for subpath in canonical(curpath).split(os.pathsep)):
Environment.set(PATH_VAR, os.pathsep.join((curpath, addpath)))
def remove_envvar_path(folder):
""" Remove *all* paths in PATH_VAR that contain the folder path. """
curpath = Environment.get(PATH_VAR, '')
folder = folder.upper()
keepers = [subpath for subpath in curpath.split(os.pathsep)
if folder not in subpath.upper()]
Environment.set(PATH_VAR, os.pathsep.join(keepers))
Sample usage:
print(Environment.get('path'))
append_path_envvar(r'C:pathomyprogramdist')
append_path_envvar(r'D:anotherpathomyprogramdist')
print(Environment.get('path'))
remove_envvar_path(r'myprogram') # remove *both* added paths
print(Environment.get('path'))
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…