继我的previous question之后,是否有可能制作一个持久更改Windows环境变量的Python脚本?
一旦python解释器终止,对os.environ的更改不会保留。如果我在UNIX上编写脚本,我可能会这样做:
set foo=`myscript.py`
但是,唉,cmd.exe没有像sh的反向行为那样的东西。我已经看到了一个非常冗长的解决方案......它确实非常可靠,我们可以改进这个:
for /f "tokens=1* delims=" %%a in ('python ..\myscript.py') do set path=%path%;%%a
当然,微软的想法有一个比这更好的解决方案!
注意:this question的完全重复。
答案 0 :(得分:5)
您可能想尝试由Mark Hammond开发的Python Win32 Extensions,它包含在ActivePython中(或可以单独安装)。您可以在Hammond's and Robinson's book中了解如何执行许多与Windows相关的任务。
使用 PyWin32 访问windows COM对象,Python程序可以使用WScript.Shell
对象的Environment Property - 环境变量的集合
答案 1 :(得分:3)
Windows为每个进程独立存储在Registry中的值设置环境变量。
但是,名为setx.exe的Windows XP Service Pack 2 Support Tools中有一个工具允许您从命令行更改全局环境变量。
答案 2 :(得分: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"
答案 3 :(得分:2)
此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)
答案 4 :(得分:1)
你啰嗦的解决方案可能是最好的主意;我不相信这可以直接来自Python。本文提出了另一种方法,使用临时批处理文件: