sha*_*kin 17 python windows environment-variables
如何从Python脚本持久修改Windows环境变量?(这是setup.py脚本)
我正在寻找一个标准功能或模块用于此目的.我已经熟悉了注册表的方式,但是对此也有任何意见.
Jon*_*ley 22
使用setx有一些缺点,特别是如果你试图附加到环境变量(例如setx PATH%Path%; C:\ mypath)这将在每次运行时重复附加到路径,这可能是一个问题.更糟糕的是,它不区分机器路径(存储在HKEY_LOCAL_MACHINE中)和用户路径(存储在HKEY_CURRENT_USER中).您在命令提示符下看到的环境变量由这两个值的串联组成.因此,在调用setx之前:
user PATH == u
machine PATH == m
%PATH% == m;u
> setx PATH %PATH%;new
Calling setx sets the USER path by default, hence now:
user PATH == m;u;new
machine PATH == m
%PATH% == m;m;u;new
Run Code Online (Sandbox Code Playgroud)
每次调用setx以追加到PATH时,系统路径都不可避免地在%PATH%环境变量中重复.这些更改是永久性的,永远不会通过重新启动重置,因此会在机器的整个生命周期中累积.
试图在DOS中弥补这一点超出了我的能力.所以我转向Python.我今天提出的解决方案,通过调整注册表来设置环境变量,包括在不引入重复项的情况下附加到PATH,如下所示:
from os import system, environ
import win32con
from win32gui import SendMessage
from _winreg import (
CloseKey, OpenKey, QueryValueEx, SetValueEx,
HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE,
KEY_ALL_ACCESS, KEY_READ, REG_EXPAND_SZ, REG_SZ
)
def env_keys(user=True):
if user:
root = HKEY_CURRENT_USER
subkey = 'Environment'
else:
root = HKEY_LOCAL_MACHINE
subkey = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
return root, subkey
def get_env(name, user=True):
root, subkey = env_keys(user)
key = OpenKey(root, subkey, 0, KEY_READ)
try:
value, _ = QueryValueEx(key, name)
except WindowsError:
return ''
return value
def set_env(name, value):
key = OpenKey(HKEY_CURRENT_USER, 'Environment', 0, KEY_ALL_ACCESS)
SetValueEx(key, name, 0, REG_EXPAND_SZ, value)
CloseKey(key)
SendMessage(
win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')
def remove(paths, value):
while value in paths:
paths.remove(value)
def unique(paths):
unique = []
for value in paths:
if value not in unique:
unique.append(value)
return unique
def prepend_env(name, values):
for value in values:
paths = get_env(name).split(';')
remove(paths, '')
paths = unique(paths)
remove(paths, value)
paths.insert(0, value)
set_env(name, ';'.join(paths))
def prepend_env_pathext(values):
prepend_env('PathExt_User', values)
pathext = ';'.join([
get_env('PathExt_User'),
get_env('PathExt', user=False)
])
set_env('PathExt', pathext)
set_env('Home', '%HomeDrive%%HomePath%')
set_env('Docs', '%HomeDrive%%HomePath%\docs')
set_env('Prompt', '$P$_$G$S')
prepend_env('Path', [
r'%SystemDrive%\cygwin\bin', # Add cygwin binaries to path
r'%HomeDrive%%HomePath%\bin', # shortcuts and 'pass-through' bat files
r'%HomeDrive%%HomePath%\docs\bin\mswin', # copies of standalone executables
])
# allow running of these filetypes without having to type the extension
prepend_env_pathext(['.lnk', '.exe.lnk', '.py'])
Run Code Online (Sandbox Code Playgroud)
它不会影响当前进程或父shell,但它会影响运行后打开的所有cmd窗口,无需重新启动,并且可以安全地编辑和重新运行多次而不会引入任何重复项.
使用外部 Windowssetx命令可能同样容易:
C:\>set NEWVAR
Environment variable NEWVAR not defined
C:\>python
Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.system('setx NEWVAR newvalue')
0
>>> os.getenv('NEWVAR')
>>> ^Z
C:\>set NEWVAR
Environment variable NEWVAR not defined
Run Code Online (Sandbox Code Playgroud)
现在打开一个新的命令提示符:
C:\>set NEWVAR
NEWVAR=newvalue
Run Code Online (Sandbox Code Playgroud)
如您所见,setx既没有为当前会话设置变量,也没有为父进程(第一个命令提示符)设置变量。但它确实在注册表中为将来的进程永久设置了变量。
我认为根本没有改变父进程环境的方法(如果有,我很想听听!)。
| 归档时间: |
|
| 查看次数: |
10981 次 |
| 最近记录: |