-
-
Notifications
You must be signed in to change notification settings - Fork 32.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:
env
is an environment whose PATH is over ~8200 characters,shell=True
,- The first argument of
args
is 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.cmd
in advance withshutil.which('subscript', path=env['PATH'])
, and pass the result tosubprocess.run()
. In fact, this step would be necessary ifshell
wasFalse
, sincesubscript.cmd
is 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