2009-01-28 46 views
7

继我的previous question之后,是否有可能创建一个持久地改变Windows环境变量的Python脚本?python脚本可以持久地更改Windows环境变量吗? (优雅地)

一旦python解释器终止,os.environ的更改不会持续。如果我是在UNIX脚本这一点,我可能会做这样的事情:

set foo=`myscript.py` 

但很可惜,CMD.EXE没有任何就像SH的后台剔行为。我看到一个非常冗长的解决方案...这AINT漂亮所以我们肯定可以改善这一点:

for /f "tokens=1* delims=" %%a in ('python ..\myscript.py') do set path=%path%;%%a 

当然在微软的心中有比这更好的解决办法!

备注:确切重​​复的this question

+0

我不认为这个问题是完全相同的副本,因为我的问题是关于仅适用于Windows。 – 2011-05-11 17:15:28

回答

1

你长时间的解决方案可能是最好的主意;我不相信这是Python直接可能的。本文提出的另一种方法,使用临时批处理文件:

http://code.activestate.com/recipes/159462/

+5

这不会持久地改变环境。它仅仅改变环境变量的副本。 – ralphtheninja 2010-07-05 13:20:42

+0

这就是我想要的! – 2011-05-11 17:15:53

+2

@Salim Fadhley如果这就是你想要的,你为什么要问你的问题有什么不同?通过接受不回答问题的答案,您会误导人们寻找信息...... – 2011-09-07 21:57:34

3

我的解决方案使用WIN32API:

import os, sys, win32api, win32con 
'''Usage: appendenv.py envvar data_to_append''' 
def getenv_system(varname, default=None): 
    ''' 
    Author: Denis Barmenkov <barmenkov at bpc.ru> 

    Copyright: this code is free, but if you want to use it, 
       please keep this multiline comment along with function source. 
       Thank you. 

    2006-01-28 15:30 
    ''' 
    v = default 
    try: 
     rkey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment') 
     try: 
      v = str(win32api.RegQueryValueEx(rkey, varname)[0]) 
      v = win32api.ExpandEnvironmentStrings(v) 
     except: 
      pass 
    finally: 
     win32api.RegCloseKey(rkey) 
    return v 

#My set function 
def setenv_system(varname, value): 
    try: 
     rkey = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, 'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment',0 ,win32con.KEY_WRITE) 
     try: 
      win32api.RegSetValueEx(rkey, varname, 0, win32con.REG_SZ, value) 
      return True 
     except Exception, (error): 
      pass 
    finally: 
     win32api.RegCloseKey(rkey) 
    return False 

if len(sys.argv) == 3: 
    value = getenv_system(sys.argv[1]) 
    if value: 
     setenv_system(sys.argv[1],value + ";" + sys.argv[2]) 
     print "OK! %s = %s" % (sys.argv[1], getenv_system(sys.argv[1])) 
    else: 
     print "ERROR: No such environment variable. (%s)" % sys.argv[1] 
else: 
    print "Usage: appendenv.py envvar data_to_append" 
1

link提供了使用的解决方案内置winreg库。

(copypasta)

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)