Description
Bug report
Bug description:
This change (935aa45, PR #103179) changed the behavior of shutil.which
so that it checks for the extensionless filename first, before checking extensions from PATHEXT. Previously, the extensionless name was not checked at all.
This is causing problems because, at least in my case, there is both an extensionless and extensioned version of the program, and the extensionless version is a bash script (which apparently can't be executed directly on Windows.)
Full Description
On a GitHub Windows shared runner, node.js is installed.
Run Get-ChildItem -Path "C:\Program Files\nodejs"
Directory: C:\Program Files\nodejs
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 9/10/2023 11:53 PM node_modules
[... elided ...]
-a--- 8/8/2023 11:20 PM 71207576 node.exe
-a--- 6/23/2023 6:02 AM 702 nodevars.bat
-a--- 8/8/2023 10:22 PM 1365 npm
-a--- 6/23/2023 6:01 AM 483 npm.cmd
-a--- 8/8/2023 10:22 PM 1567 npx
-a--- 6/23/2023 6:01 AM 539 npx.cmd
Here, npm
is a bash script, while npm.cmd
is a cmd.exe
script.
In python 3.11 (and before), shutil.which("npm")
returns "C:\\Program Files\\nodejs\\npm.CMD"
. That can be executed successfully by subprocess.run
.
In python 3.12rc3, shutil.which("npm")
returns "C:\\Program Files\\nodejs\\npm"
, which, being a bash script, appears not to be by executable by subprocess
.
subprocess.run((shutil.which("npm"), "install"))
fails with OSError: [WinError 193] %1 is not a valid Win32 application
on python 3.12rc3.
Notes
On the system in question Get-Command npm
returns C:\Program Files\nodejs\npm.cmd
. So PowerShell gets it right.
(PATHEXT
is .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.CPL
.)
I'm not absolutely convinced that this is a bug. But again, I'm also not sure how to work around it without essentially reimplementing shutil.which
.
CPython versions tested on:
3.12
Operating systems tested on:
Windows
Linked PRs
- gh-109590: Fix incorrect resolution of paths without extensions in shutil.which on win32. #109797
- gh-109590 - Update shutil.which on win32 to only give back PATHEXT matches by default #109995
- [3.12] gh-109590: Update shutil.which on Windows to prefer a PATHEXT extension on executable files (GH-109995) #110202