Summary
When PyAppify spawns the embedded Python process, clear_python_envs() removes the Path environment variable (listed in PYTHON_ENVS_TO_REMOVE). The launcher does not currently set a replacement Path/PATH for that child process.
Downstream Python code that uses subprocess.run(['powershell', ...]) (short executable name) then fails with [WinError 2] The system cannot find the file specified on Windows, because powershell.exe lives under %SystemRoot%\System32\WindowsPowerShell\v1.0\, which is not the same directory as %SystemRoot%\System32\ searched by default process creation rules.
This was observed with ok-ww (PyAppify + embedded Python + onnxocr-ppocrv5): onnxocr/check_npu.py calls PowerShell by name to query WMI for Intel NPU driver version; the exception is logged as Failed to check NPU driver version … use cpu instead.
The failure is not proof that NPU drivers are missing; it often means PowerShell could not be started under the stripped environment.
Reproduction
- Run any PyAppify-packaged app whose embedded Python eventually runs
subprocess.run(['powershell', '-NoProfile', '-Command', '...']) without an absolute path to powershell.exe.
- Observe
[WinError 2] when Path was removed and not restored for the Python child.
Root cause
src-tauri/src/utils/process.rs: PYTHON_ENVS_TO_REMOVE includes "Path"; clear_python_envs() calls env_remove for each.
src-tauri/src/execute_python.rs: after clear_python_envs(), only the small set of env vars from build_python_execution_environment is applied — no Path.
- Windows: resolving the bare name
powershell requires a Path that includes ...\WindowsPowerShell\v1.0\ (or an absolute path in the subprocess argv).
Expected behavior
Embedded Python child processes should have a minimal, intentional Path after stripping the host Path, e.g.:
- Embedded venv:
python_home\Scripts, python_home (so packaged tools still resolve first).
- System dirs from the launcher process (still has
SystemRoot): at least %SystemRoot%\System32, %SystemRoot%\System32\WindowsPowerShell\v1.0, %SystemRoot%\SysWOW64.
This preserves the original goal (avoid host Python shadowing the embedded runtime) while allowing standard Windows tools invoked by name.
Suggested fix (implementation sketch)
After cmd.clear_python_envs() in execute_python.rs (and similarly for pip / any other Command that uses clear_python_envs() on Windows), set Path and PATH to a string built from SystemRoot + embedded python_home as above.
Related downstream (optional hardening)
onnxocr-ppocrv5 check_npu.py uses ['powershell', ...]. Using the full path to %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe would reduce sensitivity to a narrow Path, but PyAppify should still restore a minimal Path for other subprocesses.
Environment
- OS: Windows 10/11
- PyAppify: current
master behavior (PYTHON_ENVS_TO_REMOVE contains Path)
- Symptom log line:
Failed to check NPU driver version: [WinError 2] ... use cpu instead.
Summary
When PyAppify spawns the embedded Python process,
clear_python_envs()removes thePathenvironment variable (listed inPYTHON_ENVS_TO_REMOVE). The launcher does not currently set a replacementPath/PATHfor that child process.Downstream Python code that uses
subprocess.run(['powershell', ...])(short executable name) then fails with[WinError 2] The system cannot find the file specifiedon Windows, becausepowershell.exelives under%SystemRoot%\System32\WindowsPowerShell\v1.0\, which is not the same directory as%SystemRoot%\System32\searched by default process creation rules.This was observed with ok-ww (PyAppify + embedded Python + onnxocr-ppocrv5):
onnxocr/check_npu.pycalls PowerShell by name to query WMI for Intel NPU driver version; the exception is logged as Failed to check NPU driver version … use cpu instead.The failure is not proof that NPU drivers are missing; it often means PowerShell could not be started under the stripped environment.
Reproduction
subprocess.run(['powershell', '-NoProfile', '-Command', '...'])without an absolute path topowershell.exe.[WinError 2]whenPathwas removed and not restored for the Python child.Root cause
src-tauri/src/utils/process.rs:PYTHON_ENVS_TO_REMOVEincludes"Path";clear_python_envs()callsenv_removefor each.src-tauri/src/execute_python.rs: afterclear_python_envs(), only the small set of env vars frombuild_python_execution_environmentis applied — noPath.powershellrequires aPaththat includes...\WindowsPowerShell\v1.0\(or an absolute path in the subprocess argv).Expected behavior
Embedded Python child processes should have a minimal, intentional
Pathafter stripping the hostPath, e.g.:python_home\Scripts,python_home(so packaged tools still resolve first).SystemRoot): at least%SystemRoot%\System32,%SystemRoot%\System32\WindowsPowerShell\v1.0,%SystemRoot%\SysWOW64.This preserves the original goal (avoid host Python shadowing the embedded runtime) while allowing standard Windows tools invoked by name.
Suggested fix (implementation sketch)
After
cmd.clear_python_envs()inexecute_python.rs(and similarly forpip/ any otherCommandthat usesclear_python_envs()on Windows), setPathandPATHto a string built fromSystemRoot+ embeddedpython_homeas above.Related downstream (optional hardening)
onnxocr-ppocrv5
check_npu.pyuses['powershell', ...]. Using the full path to%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exewould reduce sensitivity to a narrowPath, but PyAppify should still restore a minimalPathfor other subprocesses.Environment
masterbehavior (PYTHON_ENVS_TO_REMOVEcontainsPath)Failed to check NPU driver version: [WinError 2] ... use cpu instead.