This recipe facilitates getting and setting of both "user" and "system" environment variables on Windows. It uses PyWin32 (included in ActivePython) ... and works on both Python 2 and Python 3.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import sys
from subprocess import check_call
if sys.hexversion > 0x03000000:
import winreg
else:
import _winreg as winreg
class Win32Environment:
"""Utility class to get/set windows environment variable"""
def __init__(self, scope):
assert scope in ('user', 'system')
self.scope = scope
if scope == 'user':
self.root = winreg.HKEY_CURRENT_USER
self.subkey = 'Environment'
else:
self.root = winreg.HKEY_LOCAL_MACHINE
self.subkey = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
def getenv(self, name):
key = winreg.OpenKey(self.root, self.subkey, 0, winreg.KEY_READ)
try:
value, _ = winreg.QueryValueEx(key, name)
except WindowsError:
value = ''
return value
def setenv(self, name, value):
# Note: for 'system' scope, you must run this as Administrator
key = winreg.OpenKey(self.root, self.subkey, 0, winreg.KEY_ALL_ACCESS)
winreg.SetValueEx(key, name, 0, winreg.REG_EXPAND_SZ, value)
winreg.CloseKey(key)
# For some strange reason, calling SendMessage from the current process
# doesn't propagate environment changes at all.
# TODO: handle CalledProcessError (for assert)
check_call('''\
"%s" -c "import win32api, win32con; assert win32api.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')"''' % sys.executable)
|
Here's how you use it:
>>> e1 = Win32Environment(scope="system")
>>> print(e.getenv('PATH'))
>>> e2 = Win32Environment(scope="user")
>>> e2.setenv('PYTHONPATH', os.path.expanduser(r'~\mymodules'))
As you can see, the former prints the value of the system PATH environment, while the later sets a user environment variable.
This recipe is inspired by this StackOverflow answer.
Hello from the past :)
http://code.activestate.com/recipes/473800
Quick thing: You forgot to import
sys
on top!Thanks for the recipe!
Also, in the example, it should be this:
Another thing (sorry for posting so many comments), is that in the
getenv
function, the key is never closed. I'm not sure if this would have any effect, I just noticed that you closed it insetenv
, but notgetenv
.Good catch, I'm not sure either. In my actual code, I use regobj which (I believe) automatically closes open keys.