jpype простой импорт jar и запуск main () - PullRequest
2 голосов
/ 17 апреля 2019

Я пытаюсь открыть файл jar и выполнить его основную функцию, но jpype выдает ошибку, которая не имеет смысла для меня.Вот мой код:

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()

Я получаю эту ошибку: TypeError: Пакет phylonet.coalescent.CommandLine.main не может быть вызван

Я указал абсолютный путь к файлу jar,и я получил основную функцию из META-INF / MANIFEST.MF:

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

Файл JAR, который я пытаюсь открыть, называется астральным, отсюда: https://github.com/smirarab/ASTRAL

Вызов, как это работает, как и ожидалось:

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

Так почему бы и нет, когда я вызываю его с помощью jpype?

Ответы [ 2 ]

4 голосов
/ 03 мая 2019

Прежде всего, я проверил ваш код на своем собственном 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()

И код работает правильно.Более важным, чем фактическое решение является тот факт, почему ваш код не работает.Вы использовали неправильный набор параметров и указали путь к классу в прочем способе.

Заменив JClass на JPackage, код все еще работает.

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

Поскольку вы извлекаете классы из classpath правильно, единственно возможная причина - указание неверного набора параметров.После удаления -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 голос
/ 14 июня 2019

Это была классическая проблема с JPype. Если баночка не может быть загружена, JPackage вернет другой JPackage, который не может быть вызван. Распространенные причины сбоя загрузки включают

  • Загруженная JVM не поддерживает версию jar (проверьте, что getDefaultJVMPath () не является какой-то старой версией)
  • Отсутствует зависимость от jar.
  • JVM не может найти Jar как указанный путь.

Предыдущее решение заключалось в использовании java.lang.Class.forName, который печатал бы диагностику при загрузке банки. Версия 0.7.0, которая в настоящее время доступна в качестве кандидата на выпуск, устраняет эту проблему.

Также рекомендуется использовать jpype.imports или JClass вместо 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

Вы можете пометить пакет как соответствующий (классы начинаются сверху, пакеты ниже), чтобы вызвать ошибку.

...