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 in env["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 with shutil.which('subscript', path=env['PATH']), and pass the result to subprocess.run(). In fact, this step would be necessary if shell was False, since subscript.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
Bug report
Bug description:
Note: This is likely a limitation with
cmd.exeitself. Would it be possible and/or desirable to work around this limitation in thesubprocessimplementation? 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()orPopen()under the following conditions:envis an environment whose PATH is over ~8200 characters,shell=True,argsis not a full path to the executable, just a program that is expected to be found inenv["PATH"],then
subprocesswill call_winapi.CreateProcess()with:executable = 'C:\WINDOWS\system32\cmd.exe'args = 'C:\WINDOWS\system32\cmd.exe /c "subscript"'And the underlying
cmd.exeinvocation will be unable to find "subscript".Repro
Setup a small project with the following structure:
And run
py script.py.Expected result
"subscript.cmd" is executed and "Hello, world!" is printed.
Actual result
The following message is printed.
Workarounds
Performing any of the following will produce the correct output:
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.In my real situation, the call to
subprocessis 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