Обновление за апрель 2020 : я принял ответ ниже, потому что он предлагает очень хорошее и простое решение моей проблемы, но я так и не получил свой код на работу! Если кто-то уже создал что-то подобное, пожалуйста, свяжитесь со мной!
У меня есть простой скрипт my-script.py
, который очень быстро выполняет некоторые вычисления, используя указанную библиотеку c, написанную на Python
:
import sys
import special-library
def fun(x):
do something
fun(sys.argv[1])
В моем коде Java
я часто использую / называю этот скрипт в разных частях кода, используя подход ProcessBuilder
, что означает, что я просто запускаю команду python my-script.py argument
. Это означает, что каждый раз, когда я вызываю этот сценарий, мне приходится выполнять import
команды, что является самым трудоемким делом в этом (расчетная часть на самом деле быстрее).
Есть ли решение , чтобы я вызывал импорт только один раз ? Я посмотрел немного о Jython
- можно ли написать класс или что-то, что будет инициировано, и выполнить импорт один раз, а затем вызывать его функцию каждый раз, когда я хочу выполнить часть вычислений (fun
)? Кто-нибудь делал что-то подобное или есть какое-то другое решение?
Первая попытка реализации
Я пытался написать класс 'pipe' Java, который будет выполнять python сценарий один раз. Теперь скрипт непрерывно читает со стандартного ввода, и когда он получает ввод argument
, он выполняет вычисления и возвращает результат:
import sys
import special-library
def fun(x):
do something
print('END')
for arg in sys.stdin:
fun(arg)
И это работает, конечно, когда я тестирую его из командной строки и предоставляя его входными аргументами.
Класс Java выглядит следующим образом:
package my.package;
import java.io.*;
public class PythonScriptExecuter {
private static BufferedReader pythonToJavaReader;
private static PrintWriter javaToPythonWriter;
public PythonScriptExecuter() throws Exception {
String MPBNScriptFile = "fullPathToScriptFile";
ProcessBuilder pb = new ProcessBuilder("python", MPBNScriptFile);
pb.redirectErrorStream(true);
// Start script
Process p = pb.start();
pythonToJavaReader = getOutputReader(p); // from python to java
javaToPythonWriter = getInputWriter(p); // from java to python
}
// Python => Java
private static BufferedReader getOutputReader(Process p) {
return new BufferedReader(new InputStreamReader(p.getInputStream()));
}
// Java => Python
private static PrintWriter getInputWriter(Process p) {
return new PrintWriter(new OutputStreamWriter(p.getOutputStream()));
}
public static Arraylist<String> getResults(String argument) throws IOException {
// send argument to python script
javaToPythonWriter.println(argument);
//javaToPythonWriter.flush();
// get results back one by one
ArrayList<String> results = new ArrayList<>();
int count = 0;
String line;
while (!(line = pythonToJavaReader.readLine()).equals("END")) {
// process `line` string
results.add(line);
}
return results;
}
}
Итак, что я делаю, что где-то в части инициализации моего кода у меня есть эта простая строка чтобы запустить процесс:
new MPBNPythonScriptExecuter();
и позже, когда я хочу получить некоторые результаты, я использую:
String arg = "something"
Arraylist<String> res = PythonScriptExecuter.getResults(arg);
и все это висит на чтении-выходе- строка из сценария:
while (!(line = pythonToJavaReader.readLine()).equals("END"))
Есть идеи, что здесь не так?