【问题标题】:How to add to and remove from system's environment variable "PATH"?如何在系统的环境变量“PATH”中添加和删除?
【发布时间】:2014-02-03 22:57:59
【问题描述】:

如何永久将路径添加到系统的环境变量“PATH”?

如果路径不存在,我只想添加它。

我还想删除所有包含文件夹名称的路径,例如\myprogram,无论是:

C:\path\to\myprogram\dist;D:\another\path\to\myprogram\dist;

【问题讨论】:

    标签: python windows command-line registry environment-variables


    【解决方案1】:

    这里有一些你想要的东西,它类似于jaraco.windows 项目中的代码。和它一样,只使用内置的 Python 模块——因此不需要先下载和安装 pywin32 扩展。 此外,它还兼容 Python 2.6+ 和 3.x,并支持 Unicode 环境变量和值(本例中为目录路径)。

    请注意,更改永久系统级环境变量需要 Windows 管理员权限。

    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'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
        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))
    

    示例用法:

    print(Environment.get('path'))
    append_path_envvar(r'C:\path\to\myprogram\dist')
    append_path_envvar(r'D:\another\path\to\myprogram\dist')
    print(Environment.get('path'))
    remove_envvar_path(r'\myprogram')  # remove *both* added paths
    print(Environment.get('path'))
    

    【讨论】:

    • 太棒了!它确实以最好的方式回答了这个问题。为我节省了 2 小时。
    • @Vasily:不客气。请注意,如果您有兴趣,我只是做了一些小的改进。
    • 太好了。但是用户环境变量呢?您的代码只能从系统中删除 env var,而不是用户的。
    • @Gauthier:那是因为问题是关于修改系统级环境变量。我会假设用户的变量只是存储在注册表中的其他位置——可能是HKEY_CURRENT_USER\Environment
    【解决方案2】:
    import _winreg as reg
    import win32gui
    import win32con
    
    
    # read the value
    key = reg.OpenKey(reg.HKEY_CURRENT_USER, 'Environment', 0, reg.KEY_ALL_ACCESS)
    # use this if you need to modify the system variable and if you have admin privileges
    #key = reg.OpenKey(reg.HKEY_LOCAL_MACHINE, r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 0, reg.KEY_ALL_ACCESS) 
    try
        value, _ = reg.QueryValueEx(key, 'PATH')
    except WindowsError:
        # in case the PATH variable is undefined
        value = ''
    
    # modify it
    value = ';'.join([s for s in value.split(';') if not r'\myprogram' in s])
    
    # write it back
    reg.SetValueEx(key, 'PATH', 0, reg.REG_EXPAND_SZ, value)
    reg.CloseKey(key)
    
    # notify the system about the changes
    win32gui.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')
    

    【讨论】:

    • 请注意 win32guiwin32con 包含在包 pywin32 中。至少在 pywin32 的 301 版本中,您需要使用 import win32.win32gui as win32gui 而不是 import win32gui
    【解决方案3】:

    有一个python包pathtub(我是作者),可以完成这项工作。你可以在GitHub阅读代码和文档。

    安装

    pip install pathtub
    

    示例用法

    阅读路径

    from pathtub import get_path
    
    # Getting path (can be 'process' (default), 'user' or 'machine')
    user_path = get_path('user')
    
    print(user_path)
    # C:\Program Files\Java\jdk-13.0.1\bin;C:\Programs;C:\Programs\apache-maven-3.6.2\bin;C:\Programs\cloc;C:\Programs\fciv;C:\Python\Python37;C:\Python\Python37\lib\site-packages\pywin32_system32;C:\Python\Python37\Scripts;C:\texlive\2018\bin\win32;C:\Users\USER\AppData\Local\Microsoft\WindowsApps;C:\Users\USER\AppData\Local\Programs\Microsoft VS Code\bin;C:\Users\USER\AppData\Roaming\npm
    
    

    添加到路径

    from pathtub import add_to_path
    added = add_to_path(r'C:\Add this folder\to user path', mode='user')
    
    print(added)
    #True
    
    # Adding duplicate entries is prevented
    added = add_to_path(r'C:\Add this folder\to user path', mode='user')
    
    print(added)
    #False
    

    从路径中移除

    removed = remove_from_path(r'C:\Add this folder\to user path', mode='user')
    
    print(removed)
    #True
    
    # Removing non-existing folder just returns False
    removed = remove_from_path(r'C:\Add this folder\to user path', mode='user')
    
    print(removed)
    #False
    

    要求

    当前实现 (v.1.1.2) 使用 Powershell 进行永久路径修改。我只用较新的版本(Python 3.7 和 3.8)对此进行了测试,但我想它应该也适用于一些旧版本。

    【讨论】:

      【解决方案4】:

      我从您问题中的路径推断出您有兴趣在 Windows 平台上执行此操作。

      documentation 描述了这个过程:

      要以编程方式添加或修改系统环境变量,请将它们添加到 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment 注册表项,然后广播 WM_SETTINGCHANGE 消息,并将 lParam 设置为字符串“Environment”。这允许应用程序(例如 shell)获取您的更新。

      【讨论】:

      • 你知道任何可以接受参数并为你工作的python库或简单脚本吗?
      • win32xxx 可以发送消息,winreg 可以注册
      【解决方案5】:

      您应该检查os.environ。这是一个可以直接操作或通过os.putenv操作的字典:

      将名为 varname 的环境变量设置为字符串值。这样的 环境的变化会影响开始的子流程 os.system()、popen() 或 fork() 和 execv()。

      因此:

      >>> import os
      >>> os.environ["PATH"] =  path_old + ":/tmp/hallo" 
      >>> os.environ["PATH"] 
      '/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/vendor_perl:/usr/bin/core_perl:/tmp/hallo'
      

      [更新]

      根据to this answer,您可以通过 Windows 注册表使它们持久化

      【讨论】:

      • 您不能使用 Windows 注册表“神奇地”对os.environ 进行持久更改。你必须在那里写一个具体的值。您无需修改​​ os.environ 即可执行此操作。而且,您不需要阅读它:os.environ["PATH"] 的值由两个值组成:用户PATH 和系统PATH,它们存储在不同的注册表项中。您应该改为读取相应的注册表值。
      猜你喜欢
      • 2020-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-21
      • 2017-08-16
      • 2016-11-07
      • 1970-01-01
      • 2015-09-16
      相关资源
      最近更新 更多