subprocess.Popen抛出FileNotFoundError,但os.system成功运行命令。

huangapple go评论82阅读模式
英文:

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

问题

当我尝试运行任何gradle命令,例如subprocess.Popen("gradle --version")时,我会收到FileNotFoundError错误。但是当我尝试使用os.system("gradle --version")或直接从cmd运行相同的命令时,它可以正常工作。

在环境变量PATH中,我有一个"C:\Utils\gradle-6.8.3\bin"的路径。

看起来这是与环境变量有关的问题,但我似乎找不到任何解决方法。我尝试将GRADLE_HOME设置为"C:\Utils\gradle-6.8.3"或"C:\Utils\gradle-6.8.3\bin",将不同的gradle目录添加到PATH,但都没有帮助。

唯一成功运行Popen中的gradle命令的方法是:subprocess.Popen("C:/Utils/gradle-6.8.3/bin/gradle.bat --version"),但这显然不是一个有效的解决方案。

示例代码:

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 ====")

输出:

==== 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] Не удается найти указанный файл

顺便说一句,这些命令正常工作:subprocess.Popen("node --version")subprocess.Popen("python --version")

最奇怪的是,在3台PC中,只有1台PC上的gradle命令实际上可以从Popen中工作。我发现的唯一区别是"工作的机器"已设置GRADLE_HOME,并且使用由chocolatey安装的gradle,而没有将gradle添加到PATH中。所有机器都使用相同版本的python和gradle,都运行Windows 10。设置与"工作的机器"相同的环境变量配置并没有帮助,所以也许还有chocolatey执行的其他操作我不知道?

英文:

When I'm trying to run any gradle command with for example subprocess.Popen(&quot;gradle --version&quot;) i get a FileNotFoundError. But when I try the exact same command with os.system(&quot;gradle --version&quot;) 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(&quot;C:/Utils/gradle-6.8.3/bin/gradle.bat --version&quot;) but it's obviously not a valid solution.

Sample code:

import os
import subprocess

print(&quot;==== os system ====&quot;)

os.system(&quot;gradle --version&quot;)

print(&quot;==== os system ====&quot;)

print(&quot;==== subprocess popen ====&quot;)

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

print(&quot;==== subprocess popen ====&quot;)

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

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

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?

答案1

得分: 0

如果你想将相同的字符串传递给os.systemsubprocess.Popen,那么你应该添加shell=True

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

另一种调用subprocess.Popen的方法是传递参数列表:

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

你可以查阅Popen的文档,了解关于args参数的详细信息,

> args应该是程序参数的序列,否则是一个单个字符串或类似路径的对象。默认情况下,如果args是一个序列,要执行的程序是args中的第一个项目。如果args是一个字符串,其解释方式取决于平台,并在下面描述。

英文:

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

p = subprocess.Popen(&quot;gradle --version&quot;, shell=True)

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

p = subprocess.Popen([&quot;gradle&quot;, &quot;--version&quot;])

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.

huangapple
  • 本文由 发表于 2023年6月22日 18:42:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76531068.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定