1

I have this question of piping from python to java using communicate

import subprocess

str = ["haha", "hehe"]
p = subprocess.Popen("java -jar "hi.jar", stdin = subprocess.PIPE, stdout = subprocess.PIPE)
#p.communicate(str)

I would like to run communicate a list to my subprocess and obtain the output as a list

My question would be that how would java tackle this communication? As a list?

I am using this to handle it in java.

Scanner in = new Scanner(System.in)
//Not sure what to put here if i am using 
in.nextline()

I am trying to pipe a list to a java engine for processing and pipe the output as a list from java back to python

aceminer
  • 4,089
  • 9
  • 56
  • 104

3 Answers3

2

You will have to use a new line to delimit your strings.

import subprocess

l = "line 1\nline 2\nline 3"
p = subprocess.Popen(["java", "-jar", "hi.jar"], stdin = subprocess.PIPE)
p.communicate(l)

Your java code can look like this.

import java.util.Scanner;

public class ReadData
{
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            System.out.println(sc.nextLine() + " - line");
        }
    }
}

Create simple manifest file.

echo "Main-Class: ReadData" > manifest.txt

Compile java code with the javac ReadLine.java and pack the code into jar with the jar cvfm hi.jar manifest.txt *.class command.

Boris
  • 2,275
  • 20
  • 21
  • Wouldnt sc.hasNextLine() be better? I am using sc.nextline() instead of sc.next() – aceminer Mar 18 '15 at 01:45
  • Absolutely. The difference between them is that the next will stop at space, and the nextLine will go all the way till it finds '\n'. Feel free to use whichever works for you case. I'll update answer. – Boris Mar 18 '15 at 01:52
1

Because you are unable to communicate a list with the subprocess communicate function, I would communicate each list member separately, then create an array (or java.util.List because java has no primitive list) using a for loop to add each member to the array.

1

There are a few options here:

  1. Use str() or repr() to convert the list to a string representation. then parse the string in Java.
  2. Split the list into separate lines and write each to the Java sub process, which puts them back together into a list.
  3. Use JSON. Send a JSON string of the list to Java and decode it with one of the many JSON libraries available.

I'd opt for the third option, JSON, because this gives more flexibility with the types of data structures that can be communicated. e.g. you might later find yourself wanting to transfer a Python dictionary. You might also later find that you want your Java application to send a reply, and JSON can be used here too.

Python to send the list as a JSON string:

import json
import subprocess

# send a Python list...
p = subprocess.Popen("java -jar "hi.jar", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
o, e = p.communicate(json.dumps(["haha", "hehe"]))

>>> print o
handleInput():  got a JSONArray (list) containing 2 elements
haha
hehe

# send a Python dictionary...
p = subprocess.Popen("java -jar "hi.jar", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
o, e = p.communicate(json.dumps({"hee": "haw", "blah": "blah"}))
>>> print o
handleInput():  got a JSONObject (map) containing 2 items
hee: haw
blah: blah

And sample Java code to receive and parse the JSON. It can handle basic lists and dictionaries. This uses the json-simple package for the parsing:

import java.util.Scanner;
import java.util.Iterator;

import org.json.simple.JSONObject;
import org.json.simple.JSONArray;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;


class JSONMessageHandler {
    void handleInput(JSONArray list)
    {
        System.out.println(
                "handleInput():  got a JSONArray (list) containing " +
                    list.size() + " elements");

        for (Object o : list)
            System.out.println(o);
    }

    void handleInput(JSONObject map)
    {
        System.out.println(
                "handleInput():  got a JSONObject (map) containing " +
                    map.size() + " items");

        for (Iterator it = map.keySet().iterator(); it.hasNext();)
        {
            Object key = it.next();
            System.out.println(key + ": " + map.get(key));
        }
    }
}


class Hi {
    public static void main(String[] args) throws ParseException {
        Scanner in = new Scanner(System.in);
        Object obj = new JSONParser().parse(in.nextLine());
        JSONMessageHandler msgHandler = new JSONMessageHandler();

        if (obj instanceof JSONArray)
            msgHandler.handleInput((JSONArray)obj);
        else if (obj instanceof JSONObject)
            msgHandler.handleInput((JSONObject)obj);
    }
}
mhawke
  • 84,695
  • 9
  • 117
  • 138