-
-
Notifications
You must be signed in to change notification settings - Fork 33.6k
Description
Bug report
Bug description:
Note: This is likely a limitation with cmd.exe itself. Would it be possible and/or desirable to work around this limitation in the subprocess implementation? If not, then go ahead and close this bug as "will not fix". At least it will be documented for future users :)
Description
When calling subprocess.run() or Popen() under the following conditions:
envis an environment whose PATH is over ~8200 characters,shell=True,- The first argument of
argsis not a full path to the executable, just a program that is expected to be found inenv["PATH"],
then subprocess will call _winapi.CreateProcess() with:
executable = 'C:\WINDOWS\system32\cmd.exe'args = 'C:\WINDOWS\system32\cmd.exe /c "subscript"'
And the underlying cmd.exe invocation will be unable to find "subscript".
Repro
Setup a small project with the following structure:
- demo/
- scripts/
- subscript.cmd
- script.py
:: demo/scripts/subscript.cmd
@echo Hello, world!# demo/script.py
import os, sys, pathlib, subprocess
scripts_dir = pathlib.Path("scripts").resolve()
fake_path = "C:\\NotAPath"
env = os.environ.copy()
path_elems = [str(scripts_dir), env["PATH"]]
for _ in range(1000):
path_elems.append(fake_path)
env["PATH"] = os.pathsep.join(path_elems)
print("PATH length:", len(env["PATH"]))
subprocess.run("subscript", env=env, shell=True)And run py script.py.
Expected result
"subscript.cmd" is executed and "Hello, world!" is printed.
Actual result
The following message is printed.
'subscript' is not recognized as an internal or external command,
operable program or batch file.
Workarounds
Performing any of the following will produce the correct output:
- The user can resolve the path to
subscript.cmdin advance withshutil.which('subscript', path=env['PATH']), and pass the result tosubprocess.run(). In fact, this step would be necessary ifshellwasFalse, sincesubscript.cmdis not on the current process's PATH. - After some experimentation, I've found that the PATH length limit is exactly 8191 characters. Having a PATH of this length or lower will work; any longer and the above issue is observed.
In my real situation, the call to subprocess is in a library I am using and I cannot modify its arguments. In addition, in the context where this call is made, the PATH is very long by necessity.
CPython versions tested on:
3.13, 3.12, 3.11, 3.10
Operating systems tested on:
Windows