我希望从python脚本中永久修改windows中的路径变量。该脚本是一个包装器,有助于自动安装应用程序,我希望启用API将应用程序添加到路径中。
例如,我想安装一个名为micro
的程序,它的安装路径为C:UsersUSERNAMEPathtomicro
,然后将该安装路径添加到我的路径变量中,这样我就可以在终端中运行micro
。
我已经知道了两种可能的解决方案,但都不起作用:
1.使用os.environ
在python中,操作系统模块允许您读取环境变量,但不实际修改它们。例如:
program_path = "C:\Users\USERNAME\Path\to\micro"
new_path = f"{os.environ['PATH']};{program_path}"
os.environ["PATH"] = new_path
这将更新python脚本中的路径变量,但它实际上并没有在系统上修改它,这正是我想要的。
2.setx
我知道在windows中使用setx
命令可以更新路径,但由于某些原因,在windows 10上,这会破坏您的路径变量。
这个想法是,您可以从python中调用setx
命令,并使用它来更新路径变量。您应该能够键入setx path "%path%;C:UsersUSERNAMEPathtomicro"
并使其正确更新。
例如,在python代码中,它将是:
program_path = "C:\Users\USERNAME\Path\to\micro"
subprocess.Popen(f'setx path "%path%;{program_path}"')
这个应该获取当前路径变量并将程序路径附加到它,但它只是擦除整个路径,并用文字%path%和程序路径替换它。
所以现在我的路径是这样的:
%path%
C:UsersUSERNAMEPathtomicro
任何关于如何使其发挥作用的想法都将不胜感激。
好吧,经过长时间(令人恶心(的研究,我找到了解决方案。以下是我为添加到PATH变量的跨平台系统想出的方法:
def add_to_path(program_path:str):
"""Takes in a path to a program and adds it to the system path"""
if os.name == "nt": # Windows systems
import winreg # Allows access to the windows registry
import ctypes # Allows interface with low-level C API's
with winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) as root: # Get the current user registry
with winreg.OpenKey(root, "Environment", 0, winreg.KEY_ALL_ACCESS) as key: # Go to the environment key
existing_path_value = winreg.EnumValue(key, 3)[1] # Grab the current path value
new_path_value = existing_path_value + program_path + ";" # Takes the current path value and appends the new program path
winreg.SetValueEx(key, "PATH", 0, winreg.REG_EXPAND_SZ, new_path_value) # Updated the path with the updated path
# Tell other processes to update their environment
HWND_BROADCAST = 0xFFFF
WM_SETTINGCHANGE = 0x1A
SMTO_ABORTIFHUNG = 0x0002
result = ctypes.c_long()
SendMessageTimeoutW = ctypes.windll.user32.SendMessageTimeoutW
SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, 0, u"Environment", SMTO_ABORTIFHUNG, 5000, ctypes.byref(result),)
else: # If system is *nix
with open(f"{os.getenv('HOME')}/.bashrc", "a") as bash_file: # Open bashrc file
bash_file.write(f'nexport PATH="{program_path}:$PATH"n') # Add program path to Path variable
os.system(f". {os.getenv('HOME')}/.bashrc") # Update bash source
print(f"Added {program_path} to path, please restart shell for changes to take effect")
两者都不漂亮,但它确实有效。您确实需要重新启动正在运行的shell才能使其生效,但除此之外,它是完美的。