2009-12-31 7 views
2

J'ai une application python dont je ne peux pas éditer une boîte noire de mon point de vue. L'application python sait comment traiter du texte et retourner du texte traité. J'ai une autre application écrite en Java qui sait comment collecter des textes non traités.Interaction entre l'application Java et l'application Python

Etat actuel, l'application python fonctionne en mode batch toutes les x minutes.

Je veux faire le traitement python

partie du processus: Java application du texte et recueille demander l'application python pour traiter et renvoyer texte traité dans le cadre d'un flux.

Selon vous, quelle est la solution la plus simple pour cela?

Merci, Rod

+0

Comment entrée prendre le programme python? Cela n'a pas beaucoup de sens, lit-il dans un répertoire toutes les X minutes, ou depuis STDIO? Est-ce que vous exécutez le code vous-même ou quoi? – Petriborg

Répondre

6

Regardez dans Jython - vous pouvez exécuter des programmes Python directement à partir du code Java et interagir de façon transparente dans les deux sens.

+0

L'application python est une boîte noire pour moi. Je ne peux pas l'éditer. – Rod

+0

Vous devriez être capable de faire fonctionner Jython même sans changer votre code python. –

+0

Je veux traiter le Python comme une boîte fermée noire. Plus en tant que serveur. Comment python et python fonctionnent avec les sockets? – Rod

0

Exposer l'un des deux comme un service quelconque, un service Web peut-être. Une autre option consiste à porter le code python à Jython

0

Une solution possible est jpype. Cela vous permet de lancer une JVM à partir de Python et de passer des données entre eux.

Une autre solution peut être d'écrire le programme Python en tant que filtre (en lisant les données de stdin et en écrivant le résultat sur stdout), puis de l'exécuter en tant que canal. Cependant, je ne sais pas dans quelle mesure Java supporte cela - selon les docs de Sun, leur concept de tuyaux ne supporte que la communication entre les threads sur la même JVM.

4

Je ne connais rien à Jython et autres. Je suppose que c'est la meilleure solution si vous pouvez exécuter deux programmes sans exécuter un nouveau processus chaque fois que l'application Java doit transformer du texte. De toute façon, une simple preuve de concept consiste à exécuter un processus séparé de l'application Java pour le faire fonctionner. Ensuite, vous pouvez améliorer l'exécution avec tous ces outils.

Exécution d'un processus distinct de Java

String[] envprops = new String[] {"PROP1=VAL1", "PROP2=VAL2" }; 
Process pythonProc = Runtime.getRuntime().exec(
    "the command to execute the python app", 
    envprops, 
    new File("/workingdirectory")); 

// get an outputstream to write into the standard input of python 
OutputStream toPython = pythonProc.getOutputStream(); 

// get an inputstream to read from the standard output of python 
InputStream fromPython = pythonProc.getInputStream(); 

// send something 
toPython.write(.....); 
// receive something 
fromPython.read(....); 

Important: les caractères ne sont PAS octets

Beaucoup de gens ce-estiment.

Soyez prudent avec char conversions d'octets (souvenez-vous des écrivains/Les lecteurs sont pour les caractères, entrée/OutputStreams sont pour les octets, l'encodage est necesary pour convertir un un à l'autre, vous pouvez utiliser OuputStreamWriter pour convertir la chaîne en octets et envoyer, InputStreamReader à convertir les octets en caractères et les lire).

+0

Bien sûr, cela signifie que l'application python doit lire depuis le stdin et écrire dans la sortie standard. Bonne chance! – helios

+0

Wont il suffit de retourner le code de sortie du processus python? Si ce n'est pas le cas, qu'est-ce qui serait considéré comme disponible dans inputStream? – Rod

+0

Nop. Du processus invoqué (python) vous avez un STDIN et un STDOUT (et un STDERR aussi :). Java peut les accrocher, écrire dans l'un et lire l'autre. Quand vous faites printf ("...") (désolé, je ne sais pas pour Python), vous écrivez sur stdout. Lorsque vous faites quelque chose comme "dir | more" dans la ligne de commande Windows ou "ls | nl" sous Linux, vous redirigez STDOUT du premier programme vers le STDIN de la seconde. Si vous voulez le code de retour du processus, vous devez appeler pythonProc.waitFor(). Cela renvoie un int. – helios

0

Une option consiste à faire fonctionner l'application python en tant que serveur, à l'écoute des requêtes via des sockets (TCP).

2

Utilisez ProcessBuilder pour exécuter votre code Python comme un filtre:

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

public class PBTest { 

    public static void main(String[] args) { 
     ProcessBuilder pb = new ProcessBuilder("python", "-c", "print 42"); 
     pb.redirectErrorStream(true); 
     try { 
      Process p = pb.start(); 
      String s; 
      BufferedReader stdout = new BufferedReader (
       new InputStreamReader(p.getInputStream())); 
      while ((s = stdout.readLine()) != null) { 
       System.out.println(s); 
      } 
      System.out.println("Exit value: " + p.waitFor()); 
      p.getInputStream().close(); 
      p.getOutputStream().close(); 
      p.getErrorStream().close(); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 
}