将数据从 Java 程序传递到 Python 程序并返回结果
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17262364/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Passing Data from a Java program to a Python program and getting results back
提问by Soumya Simanta
What is the preferred way of passing data (a list of string) from a Java program to a Python script. The python script performs some processing on the data and then I need to get the results back in my Java program.
将数据(字符串列表)从 Java 程序传递到 Python 脚本的首选方式是什么。python 脚本对数据执行一些处理,然后我需要将结果返回到我的 Java 程序中。
Is there is a framework that allows you to do this easily?
是否有一个框架可以让您轻松地做到这一点?
EDIT: More specific requirements.
编辑:更具体的要求。
My Java program is a scheduler (runs every X minutes and Y seconds ) that connects to an external service and gets the RAW data and send it to python.
我的 Java 程序是一个调度程序(每 X 分钟和 Y 秒运行一次),它连接到外部服务并获取 RAW 数据并将其发送到 python。
I can rewrite everything in Python but that will take a me good amount of time. I was looking if there is a way to reuse what I already have.
我可以用 Python 重写所有内容,但这会花费我很多时间。我正在寻找是否有办法重用我已有的东西。
I want to use an existing Python script with minimal change. My python script uses a bunch of external libraries (e.g., numpy) The data passed from Java to Python is in Json format and the data returned by Python is also Json.
我想以最少的更改使用现有的 Python 脚本。我的python脚本使用了一堆外部库(比如numpy),Java传递给Python的数据是Json格式的,Python返回的数据也是Json。
Using sockets is an options but then I've to run server processes.
使用套接字是一个选项,但我必须运行服务器进程。
采纳答案by dilbert
I hacked this together a couple of months ago when I was faced with an similar problem. I avoided Jython because I wanted separate processes. The Java code is the server as it listens for requests but it doesn't re-connect on failure. The concept is is that the classes are extended threads that have a socket member so the send and receive commands can block the object threads and leave the host threads unaffected.
几个月前,当我遇到类似的问题时,我一起解决了这个问题。我避免使用 Jython,因为我想要单独的进程。Java 代码是服务器,因为它侦听请求,但不会在失败时重新连接。概念是这些类是具有套接字成员的扩展线程,因此发送和接收命令可以阻塞对象线程并使主机线程不受影响。
Python Code:
蟒蛇代码:
import StringIO
import re
import select
import socket
import sys
import threading
class IPC(threading.Thread):
def __init__(self, line_filter = None):
threading.Thread.__init__(self)
self.daemon = True
self.lock = threading.Lock()
self.event = threading.Event()
self.event.clear()
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.recv_buffer_size = 8192
self.buffer = StringIO.StringIO()
if(line_filter == None):
self.line_filter = lambda x: x
else:
self.line_filter = line_filter
def run(self):
self.sock.connect(("localhost", 32000))
data = True
while data:
try:
data = self.sock.recv(self.recv_buffer_size)
except socket.error, e:
print e
self.sock.close()
break
self.lock.acquire()
self.buffer.write(data)
self.lock.release()
self.event.set()
def readlines(self):
self.lock.acquire()
self.buffer.seek(0)
raw_lines = self.buffer.readlines()
self.buffer.truncate(0)
self.lock.release()
lines = map(self.line_filter, raw_lines)
return lines
proc_control = IPC()
while True:
proc_control.event.wait()
data = proc_control.readlines()
if(data):
# Do Stuff
proc_control.event.clear()
Java Code:
Java代码:
SocketIPC.java:
SocketIPC.java:
package project;
import java.net.Socket;
import java.net.ServerSocket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class SocketIPC {
public PrintWriter out;
public BufferedReader in;
Socket socket = null;
ServerSocket serverSocket = null;
ConnectionListener connlisten = null;
DataListener datalisten = null;
Thread connlisten_thread = null;
Thread datalisten_thread = null;
CommandObject ipc_event_cmd = null;
// Server thread accepts incoming client connections
class ConnectionListener extends Thread {
private int port;
ConnectionListener(int port) {
this.port = port;
}
@Override
public void run() {
try {
serverSocket = new ServerSocket(port);
socket = serverSocket.accept();
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
datalisten = new DataListener();
datalisten_thread = new Thread(datalisten);
datalisten_thread.start();
} catch (Exception e) {
System.err.println("SocketIPC creation error: " + e.getMessage());
}
}
}
// Server thread accepts incoming client connections
class DataListener extends Thread {
String data_str = null;
DataListener() {
}
@Override
public void run() {
try {
while(true) {
data_str = recv();
ipc_event_cmd.buffer.add(data_str);
ipc_event_cmd.execute();
}
} catch (Exception e) {
System.err.println("SocketIPC reading error: " + e.getMessage());
}
}
public String read() {
String ret_string = null;
if(!ipc_event_cmd.buffer.isEmpty()) {
ret_string = ipc_event_cmd.buffer.remove(0);
}
return ret_string;
}
}
public SocketIPC(int port) {
ipc_event_cmd = new CommandObject();
connlisten = new ConnectionListener(port);
connlisten_thread = new Thread(connlisten);
connlisten_thread.start();
}
public void send(String msg) {
if (out != null) {
out.println(msg);
}
}
public void flush() {
if (out != null) {
out.flush();
}
}
public void close() {
if (out != null) {
out.flush();
out.close();
try {
in.close();
socket.close();
serverSocket.close();
} catch (Exception e) {
System.err.println("SocketIPC closing error: " + e.getMessage());
}
}
}
public String recv() throws Exception {
if (in != null) {
return in.readLine();
} else {
return "";
}
}
public void set_cmd(CommandObject event_cmd) {
if (event_cmd != null) {
this.ipc_event_cmd = event_cmd;
}
}
}
CommandObject.java:
命令对象.java:
package project;
import java.util.List;
import java.util.ArrayList;
public class CommandObject {
List<String> buffer;
public CommandObject() {
this.buffer = new ArrayList<String>();
}
public void execute() {
}
}
DoStuff.java:
DoStuff.java:
package project;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Random;
public class DoStuff extends CommandObject {
public DoStuff () {
}
@Override
public void execute() {
String tmp_string = null;
while (!buffer.isEmpty()) {
tmp_string = buffer.remove(0);
// Do Stuff
}
}
}
回答by sigpwned
Sounds like a job for Jython! Jython is an embeddedable Python runtime written in Java. As long as you don't need to run your Python script in another process (e.g., want to be able to kill it, may use lots of memory, etc.), this is the best way by far.
听起来像是Jython的工作!Jython 是一个用 Java 编写的可嵌入 Python 运行时。只要您不需要在另一个进程中运行您的 Python 脚本(例如,希望能够杀死它,可能会使用大量内存等),这是目前最好的方法。
回答by Juned Ahsan
If you are trying to work Java and python together then make your life simple with Jython.
如果您正在尝试同时使用 Java 和 python,那么使用Jython让您的生活变得简单。
Jython, successor of JPython, is an implementation of the Python programming language written in Java. Jython programs can import and use any Java class. Except for some standard modules, Jython programs use Java classes instead of Python modules. Jython includes almost all of the modules in the standard Python programming language distribution, lacking only some of the modules implemented originally in C.
Jython 是 JPython 的继承者,是用 Java 编写的 Python 编程语言的实现。Jython 程序可以导入和使用任何 Java 类。除了一些标准模块,Jython 程序使用 Java 类而不是 Python 模块。Jython 包含标准 Python 编程语言发行版中的几乎所有模块,仅缺少一些最初用 C 实现的模块。
Assuming you have java lib in your python path. Here is a code snippet to give you an idea how simple it is to use the java classes:
假设您的 python 路径中有 java lib。这是一个代码片段,可让您了解使用 java 类是多么简单:
'''
Import JavaUtilities class from a java package
'''
from com.test.javalib import JavaUtilities
'''
Call a java method
'''
response = JavaUtilities.doSomething();