JAVA与CPython的互动

时间:2016-09-12 07:49:01

标签: java python process cpython

我的目标:

当我从命令行运行Python(CPython)时(不是Jython,因为它不支持像NumPy这样的软件包)我可以交互式地编写代码行并从输出中查看结果。

我的目标是在JAVA中以编程方式执行此操作。我试图这样做:

代码:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class PythonProcess {
    private Process proc;
    private BufferedReader stdInput;
    private BufferedReader stdError;
    private BufferedWriter stdOutput;

    public PythonProcess() {
        Runtime rt = Runtime.getRuntime();
        String[] commands = { "python.exe" };
        try {
            proc = rt.exec(commands);
            stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
            stdOutput = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String executeCommand(String command) throws IOException {
        stdOutput.write(command + "\n");
        stdOutput.newLine();
        String s = null;
        StringBuffer str = new StringBuffer();
        while ((s = stdInput.readLine()) != null) {
            str.append(s);
        }
        return str.toString();
    }

    public void initialize() throws IOException {
        // will create a file - if correctly executed in python 
        stdOutput.write("f = open('c:/downloads/deleteme.txt','w')");
        stdOutput.newLine();
        stdOutput.write("f.write('hi there, I am Python \n')");
        stdOutput.newLine();
        stdOutput.write("f.close()");
        stdOutput.newLine();
        stdOutput.flush();
    }

    public static void main(String[] args) throws IOException {
        PythonProcess proc = new PythonProcess();
        proc.initialize(); // time demanding initialization
        for (int i = 0; i < 10; i++) {
            String out = proc.executeCommand("print \"Hello from command line #"+i+"\"");
            System.out.println("Output: " + out);
        }
    }
}

问题:

由于未创建文件c:/downloads/deleteme.txt,因此似乎Python中不执行 stdOutput 在initialize()方法中传递的代码。稍后,当调用 executeCommand 方法时,我也无法读取 stdInput 的任何输出。

问题:

  1. 有没有简单的方法来修复代码?
  2. 有人能指出一些例子我如何与python进行交互,例如通过客户端 - 服务器方式
  3. 还是其他任何想法?
  4. BTW1:Jython不是要走的路,因为我需要执行python不支持的CPython指令。

    BTW2:我知道我可以通过String [] commands = {&#34; python.exe&#34;以非交互方式执行python脚本&#34; script.py&#34;} ;.问题是当初始化花费大量时间时,这将意味着重大的性能问题。

1 个答案:

答案 0 :(得分:0)

遗憾的是,无法与Python进程直接交互。而不是使用TCP套接字的解决方案:

<强> PythonServer.java

package pythonexample;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class PythonServer {
    public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder   ps=new ProcessBuilder("python.exe","tcpServer.py");
        ps.redirectErrorStream(true);
        System.out.println("Starting Python server.");
        Process pr = ps.start();  

        BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
        String line;
        while ((line = in.readLine()) != null) {
            System.out.println(line);
        }
        pr.waitFor();

        in.close();
        System.exit(0);
    }
}

<强> tcpServer.py

import socket

# DO INITIALIZATION

TCP_IP = '127.0.0.1'
TCP_PORT = 5006
BUFFER_SIZE = 20  # Normally 1024, shorter if we want fast response

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)

while 1:
    print 'Waiting for connection'
    conn, addr = s.accept()
    print 'Connection address:', addr
    if addr[0] == '127.0.0.1': # security - only local processes can connect
        data = conn.recv(BUFFER_SIZE)
        print "received data:", data
        res = eval(data)
        print "Sending result:", res
        conn.send("This is reply from Python " + str(res) + "\n")
conn.close()

<强> PythonClient.java

package pythonexample;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class PythonClient {
    public static void main(String[] args) throws IOException {
        String serverAddress = "127.0.0.1";
        Socket s = new Socket(serverAddress, 5006);

        // do this in loop if needed
        String result = sendCommand(s, "1+1                                    \n");
        System.out.println("Received result: "+result);

        // closing socket 
        s.close();
    }

    private static String sendCommand(Socket s, String command) throws IOException {
        BufferedWriter ouput = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        ouput.write(command);
        ouput.flush();

        BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String answer = input.readLine();
        return answer;
    }
}

首先执行PythonServer类,初始化服务器。然后执行将数据发送到服务器并获取结果的PythonClient。

当然所有功能,如NumPy和其他功能,例如,不支持Jython现已上市。