Search code examples
pythongradlesubprocesspopenos.system

subprocess.Popen throws FileNotFoudError but os.system successefuly runs the command


When I'm trying to run any gradle command with for example subprocess.Popen("gradle --version") i get a FileNotFoundError. But when I try the exact same command with os.system("gradle --version") or directly from cmd it work perfectly fine. In PATH I've got a "C:\Utils\gradle-6.8.3\bin"

Looks like it's some problem with environment variables but I cant seem to find any solution. I tried setting GRADLE_HOME to "C:\Utils\gradle-6.8.3" or to "C:\Utils\gradle-6.8.3\bin", adding different directories of gradle to PATH but nothing helped.

The only way I successefuly ran a gradle command from Popen was: subprocess.Popen("C:/Utils/gradle-6.8.3/bin/gradle.bat --version") but it's obviously not a valid solution.

Sample code:

import os
import subprocess

print("==== os system ====")

os.system("gradle --version")

print("==== os system ====")

print("==== subprocess popen ====")

p = subprocess.Popen("gradle --version", stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, err = p.communicate()
print(f"return code: {p.returncode}")

print("==== subprocess popen ====")

Output:

==== os system ====

------------------------------------------------------------
Gradle 6.8.3
------------------------------------------------------------

Build time:   2021-02-22 16:13:28 UTC
Revision:     9e26b4a9ebb910eaa1b8da8ff8575e514bc61c78

Kotlin:       1.4.20
Groovy:       2.5.12
Ant:          Apache Ant(TM) version 1.10.9 compiled on September 27 2020
JVM:          1.8.0-adoptopenjdk (Oracle Corporation 25.71-b00)
OS:           Windows 10 10.0 amd64

==== os system ====       
==== subprocess popen ====
Traceback (most recent call last):
  File "c:\Projects\Tanks\tanks\Buildmachine\BuildScripts\test.py", line 12, in <module>
    p = subprocess.Popen("gradle --version", stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 969, in __init__       
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1438, in _execute_child
    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
FileNotFoundError: [WinError 2] Не удается найти указанный файл

By the way these work fine: subprocess.Popen("node --version"), subprocess.Popen("python --version")

And the strangest thing is that on 1 out of 3 PC's gradle commands actually work from Popen. The only difference I found is that "the working machine" has GRADLE_HOME set and uses gradle installed by chocolatey and does not have gradle in PATH. All machines have the same python and gradle versions and all have Windows 10. Setting same environment variables configuration as on "the working machine" didn't help, so maybe there's something else chocolatey did that I didn't?


Solution

  • If you want to pass the same string for os.system to subprocess.Popen, then you should add shell=True:

    p = subprocess.Popen("gradle --version", shell=True)
    

    Another way to call subprocess.Popen is passing a list of arguments:

    p = subprocess.Popen(["gradle", "--version"])
    

    You could check the documentation for Popen's first argument args,

    args should be a sequence of program arguments or else a single string or path-like object. By default, the program to execute is the first item in args if args is a sequence. If args is a string, the interpretation is platform-dependent and described below.