从 Java 执行 julia 脚本
execute julia scripts from Java
我正在使用 ZeroMQ 编写 Julia 脚本。
我的目标是在两个脚本之间与 ZMQ 通信。这是一个例子:
# script1
using ZMQ
ctx = ZMQ.Context()
sockDealer = ZMQ.Socket(ctx, DEALER)
ZMQ.set_identity(sockDealer, "idA")
ZMQ.connect(sockDealer, "tcp://localhost:5555")
ZMQ.send(sockDealer, "hello world!")
ZMQ.close(sockDealer)
ZMQ.close(ctx)
#script2
using ZMQ
function pollrecv(socket::ZMQ.Socket,zmsg::Message)
rc = -1
while true
rc = ccall((:zmq_msg_recv, ZMQ.zmq), Cint, (Ptr{Message}, Ptr{Void}, Cint),
&zmsg, socket.data, ZMQ.ZMQ_DONTWAIT)
if rc == -1
# Base.Libc.EAGAIN = 11
# Problem unsolved: Failure to find Base.Libc.EAGAIN
if !(ZMQ.zmq_errno() == 11)
throw(ZMQ.StateError(ZMQ.jl_zmq_error_str()))
end
return false
else
ZMQ.get_events(socket) != 0 && notify(socket)
break
end
end
return true
end
ctx = ZMQ.Context()
sockRouter = ZMQ.Socket(ctx, ROUTER)
ZMQ.bind(sockRouter, "tcp://*:5555")
fini = false
while !fini
println("listening...")
idSock = Message()
while pollrecv(sockRouter, idSock)
msg = ZMQ.recv(sockRouter)
println("msg recv: " * bytestring(msg))
fini = true
end
sleep(1)
end
ZMQ.close(sockRouter)
ZMQ.close(ctx)
我可以在命令提示符下使用 Julia 执行它们。一切顺利。脚本2可以接收到脚本1的消息。
现在,我需要从 Java 执行它们。这意味着我需要创建一个类似于控制器的 java 项目。这是我的 Java 项目:
public class Container {
private Vector<String[]> commands;
public Container() {
this.commands = new Vector<String[]>();
}
public void addCommand(String[] strs) {
this.commands.addElement(strs);
}
public void execute() {
for(int i = 0; i < this.commands.size(); i++) {
try {
Process p = Runtime.getRuntime().exec(this.commands.get(i));
if(p.waitFor() != 0){
System.err.println("exit value = " + p.exitValue());
}
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuffer stringBuffer = new StringBuffer();
String line = null;
while((line = in.readLine()) != null){
stringBuffer.append(line + "-");
}
System.out.println(stringBuffer.toString());
} catch (IOException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
} catch(InterruptedException e){
System.err.println(e);
}
}
}
}
//main
public class Main {
public static void main(String[] args) {
Container c = new Container();
String[] script1 = {"/usr/bin/julia", "/home/thomas/Julia/script1.jl"};
String[] script2 = {"/usr/bin/julia", "/home/thomas/Julia/script2.jl"};
c.addCommand(script1);
c.addCommand(script2);
c.execute();
}
}
然而,当我 运行 我的 java 项目时,我可以看到它保持 运行ning 但我在控制台上看不到任何东西:没有结果,没有消息, 没有报错。
我认为我的 java 项目有问题。
您需要同时 运行 这两个脚本:script2
是服务器脚本,所以当您 运行 [=15] 时它应该是 运行ning =].现在,Process.waitFor() 将等待客户端脚本 script1
完成,然后在下一个 for
迭代中执行服务器脚本 script2
。
您可以这样启动它们:
String[] clientScript = { "/usr/bin/julia", "/home/thomas/Julia/script1.jl" };
String[] serverScript = { "/usr/bin/julia", "/home/thomas/Julia/script2.jl" };
Process server = Runtime.getRuntime().exec(serverScript);
Process client = Runtime.getRuntime().exec(clientScript);
并实例化两个线程以读取它们的输出:
(new ProcessReader(server)).start();
(new ProcessReader(client)).start();
使用
public class ProcessReader extends Thread {
private Process p;
public ProcessReader(Process p) {
this.p = p;
}
@Override
public void run() {
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
try {
String line;
while ((line = in.readLine()) != null) {
System.out.println("Read: " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
不过,由于 clientScript
不产生任何输出,您可以
启动脚本,只读取服务器脚本的输出——不需要线程。
还有一件事需要考虑:在 clientScript
尝试连接之前,serverScript
必须是 listening...
。所以你可能想这样做:
Process server = Runtime.getRuntime().exec(serverScript);
BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
if ( in.readLine().equals("listening...") ) {
Process client = Runtime.getRuntime().exec(clientScript);
String line;
while ( (line=in.readLine()) != null )
System.out.println("Read: " + line );
}
由于这不是您问题的具体答案,这可能对您或其他尝试类似工作的用户有所帮助。
JuliaCaller 是用于从 Java 调用 Julia 的早期库。它将 Julia 可执行文件作为 Java 进程执行,并在 Julia 端执行 运行s 脚本。此脚本打开一个侦听给定端口号的 TCP 服务器。然后执行从 Java 发送的每个命令、语句或表达式,并将结果以 JSON 格式发送回 Java。
该库还实现了标准 javax.script 接口,这意味着 Julia 库、函数和程序可以 运行 像在 Java 中实现的脚本语言(模仿) .
示例如下:
Constants.setProperties(Constants.JULIA_PATH, "/usr/local/bin/julia");
Constants.setProperties(Constants.JULIA_PORT, "8001");
// Creating a scripting interface for Julia
manager = new ScriptEngineManager();
engine = manager.getEngineByName("Julia");
// Sending command 'a = 3' to Julia from Java
engine.eval("a = 3");
// Handling the result in Java
Object a = engine.get("a");
GitHub 页面中提供了更多示例。
我正在使用 ZeroMQ 编写 Julia 脚本。
我的目标是在两个脚本之间与 ZMQ 通信。这是一个例子:
# script1
using ZMQ
ctx = ZMQ.Context()
sockDealer = ZMQ.Socket(ctx, DEALER)
ZMQ.set_identity(sockDealer, "idA")
ZMQ.connect(sockDealer, "tcp://localhost:5555")
ZMQ.send(sockDealer, "hello world!")
ZMQ.close(sockDealer)
ZMQ.close(ctx)
#script2
using ZMQ
function pollrecv(socket::ZMQ.Socket,zmsg::Message)
rc = -1
while true
rc = ccall((:zmq_msg_recv, ZMQ.zmq), Cint, (Ptr{Message}, Ptr{Void}, Cint),
&zmsg, socket.data, ZMQ.ZMQ_DONTWAIT)
if rc == -1
# Base.Libc.EAGAIN = 11
# Problem unsolved: Failure to find Base.Libc.EAGAIN
if !(ZMQ.zmq_errno() == 11)
throw(ZMQ.StateError(ZMQ.jl_zmq_error_str()))
end
return false
else
ZMQ.get_events(socket) != 0 && notify(socket)
break
end
end
return true
end
ctx = ZMQ.Context()
sockRouter = ZMQ.Socket(ctx, ROUTER)
ZMQ.bind(sockRouter, "tcp://*:5555")
fini = false
while !fini
println("listening...")
idSock = Message()
while pollrecv(sockRouter, idSock)
msg = ZMQ.recv(sockRouter)
println("msg recv: " * bytestring(msg))
fini = true
end
sleep(1)
end
ZMQ.close(sockRouter)
ZMQ.close(ctx)
我可以在命令提示符下使用 Julia 执行它们。一切顺利。脚本2可以接收到脚本1的消息。
现在,我需要从 Java 执行它们。这意味着我需要创建一个类似于控制器的 java 项目。这是我的 Java 项目:
public class Container {
private Vector<String[]> commands;
public Container() {
this.commands = new Vector<String[]>();
}
public void addCommand(String[] strs) {
this.commands.addElement(strs);
}
public void execute() {
for(int i = 0; i < this.commands.size(); i++) {
try {
Process p = Runtime.getRuntime().exec(this.commands.get(i));
if(p.waitFor() != 0){
System.err.println("exit value = " + p.exitValue());
}
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuffer stringBuffer = new StringBuffer();
String line = null;
while((line = in.readLine()) != null){
stringBuffer.append(line + "-");
}
System.out.println(stringBuffer.toString());
} catch (IOException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
} catch(InterruptedException e){
System.err.println(e);
}
}
}
}
//main
public class Main {
public static void main(String[] args) {
Container c = new Container();
String[] script1 = {"/usr/bin/julia", "/home/thomas/Julia/script1.jl"};
String[] script2 = {"/usr/bin/julia", "/home/thomas/Julia/script2.jl"};
c.addCommand(script1);
c.addCommand(script2);
c.execute();
}
}
然而,当我 运行 我的 java 项目时,我可以看到它保持 运行ning 但我在控制台上看不到任何东西:没有结果,没有消息, 没有报错。
我认为我的 java 项目有问题。
您需要同时 运行 这两个脚本:script2
是服务器脚本,所以当您 运行 [=15] 时它应该是 运行ning =].现在,Process.waitFor() 将等待客户端脚本 script1
完成,然后在下一个 for
迭代中执行服务器脚本 script2
。
您可以这样启动它们:
String[] clientScript = { "/usr/bin/julia", "/home/thomas/Julia/script1.jl" };
String[] serverScript = { "/usr/bin/julia", "/home/thomas/Julia/script2.jl" };
Process server = Runtime.getRuntime().exec(serverScript);
Process client = Runtime.getRuntime().exec(clientScript);
并实例化两个线程以读取它们的输出:
(new ProcessReader(server)).start();
(new ProcessReader(client)).start();
使用
public class ProcessReader extends Thread {
private Process p;
public ProcessReader(Process p) {
this.p = p;
}
@Override
public void run() {
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
try {
String line;
while ((line = in.readLine()) != null) {
System.out.println("Read: " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
不过,由于 clientScript
不产生任何输出,您可以
启动脚本,只读取服务器脚本的输出——不需要线程。
还有一件事需要考虑:在 clientScript
尝试连接之前,serverScript
必须是 listening...
。所以你可能想这样做:
Process server = Runtime.getRuntime().exec(serverScript);
BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
if ( in.readLine().equals("listening...") ) {
Process client = Runtime.getRuntime().exec(clientScript);
String line;
while ( (line=in.readLine()) != null )
System.out.println("Read: " + line );
}
由于这不是您问题的具体答案,这可能对您或其他尝试类似工作的用户有所帮助。
JuliaCaller 是用于从 Java 调用 Julia 的早期库。它将 Julia 可执行文件作为 Java 进程执行,并在 Julia 端执行 运行s 脚本。此脚本打开一个侦听给定端口号的 TCP 服务器。然后执行从 Java 发送的每个命令、语句或表达式,并将结果以 JSON 格式发送回 Java。
该库还实现了标准 javax.script 接口,这意味着 Julia 库、函数和程序可以 运行 像在 Java 中实现的脚本语言(模仿) .
示例如下:
Constants.setProperties(Constants.JULIA_PATH, "/usr/local/bin/julia");
Constants.setProperties(Constants.JULIA_PORT, "8001");
// Creating a scripting interface for Julia
manager = new ScriptEngineManager();
engine = manager.getEngineByName("Julia");
// Sending command 'a = 3' to Julia from Java
engine.eval("a = 3");
// Handling the result in Java
Object a = engine.get("a");
GitHub 页面中提供了更多示例。