【问题标题】:Maven command mvn runs without errors from terminal but not from pythonMaven 命令 mvn 从终端运行没有错误,但从 python 运行没有错误
【发布时间】:2020-07-02 11:13:15
【问题描述】:

我正在尝试从 python 脚本运行一个 maven 项目。我已经安装了apache maven。 从 pom.xml 所在项目文件夹中的终端运行命令:mvn exec:java -D"exec.mainClass"="org.matsim.project.RunMatsim",不会产生任何错误并且项目运行正常。

但是当从我的 python 脚本运行以下代码时

import subprocess as sp

def execute(cmd):
    popen = sp.Popen(cmd, stdout=sp.PIPE, universal_newlines=True,shell=True)
    for stdout_line in iter(popen.stdout.readline, ""):
        yield stdout_line 
    popen.stdout.close()
    return_code = popen.wait()
    if return_code:
        raise sp.CalledProcessError(return_code, cmd)

for path in execute(["mvn", "exec:java" ,'-D"exec.mainClass"="org.matsim.project.MatsimRun"']):
    print(path, end="")

我收到以下错误:

[错误] 没有为此构建指定目标。您必须以 : 或 :[:]: 格式指定有效的生命周期阶段或目标。可用的生命周期阶段有:验证、初始化、生成源、流程源、生成资源、流程资源、编译、流程类、生成测试源、流程测试源、生成测试资源、流程-test-resources、test-compile、process-test-classes、test、prepare-package、package、pre-integration-test、integration-test、post-integration-test、verify`

为什么会这样?有什么问题?

两种情况(终端、python 脚本)出现的警告相同。

【问题讨论】:

  • 使用 R system('mvn exec:java -D"exec.mainClass"="org.matsim.project.RunMatsim"') 运行相同的命令可以正常工作,如果这有帮助的话。

标签: java python-3.x shell maven subprocess


【解决方案1】:

就个人而言,我认为在不同编程环境中编码的程序员面临的最大问题之一是使用双引号 ("") 和单引号 (''),这可能会导致像您这样的烦人问题。

处理,你可以使用插件而不是使用maven的内置命令。将以下插件添加到您的 pom.xml 文件中,然后更轻松地执行您的应用程序。

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>exec-maven-plugin</artifactId>
  <version>1.4.0</version>
  <configuration>
    <mainClass>org.matsim.project.MatsimRun</mainClass>
  </configuration>
</plugin>

在上述插件中,假设你的Main类是org.matsim.project.MatsimRun。要从命令行触发插件,只需运行:

mvn exec:java

我希望这会有所帮助!

【讨论】:

    【解决方案2】:

    只需更改以下行

    ["mvn", "exec:java" ,'-D"exec.mainClass"="org.matsim.project.MatsimRun"']
    

    ["mvn", "exec:java" ,"-D\"exec.mainClass\"=\"org.matsim.project.MatsimRun\""]
    

    【讨论】:

      【解决方案3】:

      通常当我从 java/python/etc 运行程序时遇到 args 问题。我将要使用的命令包装在 sh -c 中,如下所示:

      sp.Popen(['/bin/sh', '-c', "mvn exec:java -D\"exec.mainClass\"=\"org.matsim.project.MatsimRun\""])
      

      以上对我来说似乎工作正常。请注意这样做可能存在安全隐患,请确保作为sh 的第三个参数输入的命令永远不会连接到仇恨互联网。

      好的,现在为什么您的代码不起作用?

      pythondocsshell=True 相当于:

      Popen(['/bin/sh', '-c', args[0], args[1], ...])
      

      所以一个很好的假设是sh 忽略了arg[1] 和其他参数。 您可以通过以下方式进行测试:

      <censored>@debian:~$ sh -c echo "sfaklg"
      
      <censored>@debian:~$ 
      

      观察echo 如何没有得到它期望的参数。这在许多不同的引用方法/shell中是一致的:

      <censored>@debian:~$ dash -c echo "sfaklg"
      
      <censored>@debian:~$ bash -c echo "sfaklg"
      
      <censored>@debian:~$ zsh -c echo "sfaklg"
      
      <censored>@debian:~$ zsh -c echo sfaklg
      
      <censored>@debian:~$ bash -c echo sfaklg
      
      <censored>@debian:~$ 
      
      

      bash 的手册页说:

      如果存在 -c 选项,则从第一个非选项参数 command_string 中读取命令。如果 command_string 之后有参数,则将第一个参数分配给 $0,并将任何剩余的参数分配给位置参数。对 $0 的赋值设置了 shell 的名称,用于警告和错误消息。

      换句话说,sh -c 用于运行期望 args 与 $1$2、...一起传递的 shell 脚本。

      那你该怎么办?

      怀疑您想在 shell 中运行 maven,因为它需要设置 JAVA_HOME 或类似的环境变量。这个question 提供了如何设置/修改环境变量的示例,尽管您可能仍然需要shell=True。这个answer 还建议使用 env 命令覆盖环境变量。

      最后,您可能会发现这个question 很有帮助。

      【讨论】:

        【解决方案4】:

        尝试去掉exec.mainClass周围的双引号,即:

        mvn exec:java -Dexec.mainClass="org.matsim.project.MatsimRun"
        

        代替:

        mvn exec:java -D"exec.mainClass"="org.matsim.project.MatsimRun"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-16
          • 1970-01-01
          • 1970-01-01
          • 2017-10-24
          相关资源
          最近更新 更多