jpype simple jar import and run main()

时间:2019-04-16 22:33:34

标签: java python jpype

I'm trying to open a jar file and execute it's main function, but jpype is throwing an error that doesn't make sense to me. Here is my code:

jpype.startJVM(jpype.getDefaultJVMPath(), '-Djava.class.path="%s"' % jar)
CommandLine = jpype.JPackage('phylonet').coalescent.CommandLine
CommandLine.main(['-i', input_file, '-o', output_file])
jpype.shutdownJVM()

I get this error: TypeError: Package phylonet.coalescent.CommandLine.main is not Callable

I've provided the absolute path to the jar file, and I've gotten the main function from META-INF/MANIFEST.MF:

cat tmp/META-INF/MANIFEST.MF | grep Main-Class
Main-Class: phylonet.coalescent.CommandLine

The jar file I'm trying to open is called astral, from here: https://github.com/smirarab/ASTRAL

Calling it like this works as expected:

java -Djava.class.path="./astral.jar"

So why not when I call it with jpype?

2 个答案:

答案 0 :(得分:3)

首先,我已经在自己的jarfile上测试了您的代码。确实,我遇到了这样的错误:

TypeError: Package clip.frontend.Start.main is not Callable

然后,在仔细阅读文档之后,我使用了另一种方法。

import jpype

# I've used other set of parameters to JVM, and modified a bit your classpath setting.
jpype.startJVM(jpype.getDefaultJVMPath(), "-ea", "-Djava.class.path=clip.jar")

# Second difference, I decided to use JClass because it was more clear for me.
# Parameter array was kept empty.
jpype.JClass("clip.frontend.Start").main([])
jpype.shutdownJVM()

输出正确:

% python2 main.py
2 2
+>+[<[>>+>+<<<-]>>[<<+>>-]>[[-]>>>>>>+<<<<<<<<<[-]>[-]>>>>>>>>[<<<<<<<<+>+>>>>>>>-]
<<<<<<<[>>>>>>>+<<<<<<<-]>>>>>>>[-]<<<<<<]<<<[>>+>+<<<-]>>[<<+>>-]>[[-]>>>>>>++
[<<<<<+>>>>>>>>>>>>+<<<<<<<-]<<<<<[>>>>>+<<<<<-]>>>>>>>>>>>>>[>>]+<<[<<]>[>[>>]
<+<[<<]>-]<<<<<<<[-]++[<<<<<+>>>>>>>>>>>>+<<<<<<<-]<<<<<[>>>>>+<<<<<-]>>>>>>>>>>>>>
[>>]+<<[<<]>[>[>>]<+<[<<]>-]<<<<<<<[-]#JVM has been shutdown

现在,我决定翻译我的解决方案以匹配您的问题:

import jpype
jpype.startJVM(jpype.getDefaultJVMPath(), "-ea", "-Djava.class.path=astral.jar")
jpype.JClass("phylonet.coalescent.CommandLine").main([])
jpype.shutdownJVM()

并且代码正常工作。比实际的解决方案更重要的是事实,为什么您的代码不起作用。您使用了错误的参数集,并以 other 方式指定了类路径。

用JPackage替换JClass,代码仍然有效。

import jpype
jpype.startJVM(jpype.getDefaultJVMPath(), "-ea", "-Djava.class.path=astral.jar")
jpype.JPackage('phylonet').coalescent.CommandLine.main([])
jpype.shutdownJVM()

由于从类路径中提取类的方法是正确的,所以唯一可能的原因是指定了无效的参数集。删除-ea后,代码仍然有效,因此您在此代码段中犯了错误。

'-Djava.class.path="%s"' % jar

实际上,我用它来代替我的答案,而bam,代码产生的结果是:

TypeError: Package phylonet.coalescent.CommandLine.main is not Callable

这意味着,该参数包含以下内容:

-Djava.class.path="astral.jar"

代替关注

-Djava.class.path=astral.jar

引号放错了位置,并导致结果错误。

答案 1 :(得分:1)

这是JPype的经典问题。如果无法加载jar,则JPackage将返回另一个不可调用的JPackage。导致加载失败的常见原因包括

  • 加载的JVM不支持jar版本(请检查getDefaultJVMPath()是否不是旧版本)
  • 缺少jar依赖项。
  • JVM找不到Jar作为指定路径。

先前的解决方案是使用java.lang.Class.forName,它将在jar加载时打印诊断信息。当前可以作为候选发布版本的0.7.0版本解决了此问题。

此外,建议您在导入类时使用jpype.importsJClass而不是JPackage。这将更加安全,因为它将报告更有意义的错误。例如:

import jpype
import jpype.imports

jpype.startJVM()
jpype.imports.registerDomain('phylonet')  # This is required as phylonet is not a tld

from phylonet.coalescent import CommandLine

您可以将包装标记为合格(类从上开始,包装从下开始)以强制执行错误。