我已经创建了一个命令行程序,我想分发给一些工作人员。让他们全部安装python解释器是不切实际的。因此,我使用PyInstaller创建了一个.exe文件。然而,我开始意识到,大多数人甚至不知道如何导航到.exe所在的目录,以便调用它。 (到目前为止,我还没有弄清楚如何在点击时让程序运行。)有没有办法让程序在第一次运行时将它自己添加到用户sys PATH中,或者这样做需要安装人员?谢谢!
答案 0 :(得分:1)
常见陷阱是阅读PATH
env。使用os.environ('PATH')
变量。这将是大错误,因为此变量包含用户&系统路径混合在一起。这是PATH
变量的一个特例。
您需要做的是从注册表(用户部分)获取PATH
env变量,在需要时更新它,然后将其写回。
您可以使用winreg
模块实现该功能,修改用户PATH
环境变量(如果此特定用户不存在则创建)
PATH
变量os.path.dirname(__file__)
)PATH
用户环境。必要时带有更新路径列表的变量代码:
import winreg,os
script_directory = os.path.dirname(__file__)
paths = []
key_type = winreg.REG_EXPAND_SZ # default if PATH doesn't exist
try:
keyQ = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Environment', 0, winreg.KEY_QUERY_VALUE)
path_old, key_type = winreg.QueryValueEx(keyQ, "PATH")
winreg.CloseKey(keyQ)
paths = path_old.split(os.pathsep)
except WindowsError:
pass
if script_directory in paths:
# already set, do nothing
print(paths)
else:
# add the new path
paths.append(script_directory)
# change registry
keyQ = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Environment', 0, winreg.KEY_WRITE)
winreg.SetValueEx(keyQ, 'PATH', 0, key_type, os.pathsep.join(paths))
winreg.CloseKey(keyQ)
请注意,用户必须注销/登录才能使更改生效。另一种解决方案是在setx
变量上调用PATH
。系统调用,丑陋但立即生效。
# change registry with immediate effect
import subprocess
subprocess.call(["setx","PATH",os.pathsep.join(paths)])
或者,由于eryksun的礼貌,一些python代码将注册表更改传播到新进程。无需注销,无需丑陋setx
,只需使用以下代码致电broadcast_change('Environment')
:
import ctypes
user32 = ctypes.WinDLL('user32', use_last_error=True)
HWND_BROADCAST = 0xFFFF
WM_SETTINGCHANGE = 0x001A
SMTO_ABORTIFHUNG = 0x0002
ERROR_TIMEOUT = 0x05B4
def broadcast_change(lparam):
result = user32.SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE,
0, ctypes.c_wchar_p(lparam), SMTO_ABORTIFHUNG, 1000, None)
if not result:
err = ctypes.get_last_error()
if err != ERROR_TIMEOUT:
raise ctypes.WinError(err)
(似乎我必须用最后一点重构我自己的一些代码:))
ENV。变量读取代码取自此处:How to return only user Path in environment variables without access to Registry?