Skip to content

On Windows, shutil.which incorrectly resolves to non-executable extensionless files (python >= 3.12.0b1) #109590

Closed
@dairiki

Description

@dairiki

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.12only security fixes3.13bugs and security fixesOS-windowsstdlibPython modules in the Lib dirtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions