5
votes

Problème lors de l'appel de code Python à partir de Java (sans utiliser jython)

J'ai trouvé cela comme l'un des moyens d'exécuter (en utilisant la méthode exec ()) un script python à partir de java. J'ai une simple déclaration d'impression dans un fichier python. Cependant, mon programme ne fait rien lorsque je l'exécute. Il n'imprime pas l'instruction écrite dans le fichier python ni ne lève d'exception. Le programme s'arrête juste de ne rien faire:

Process p = Runtime.getRuntime().exec("C:\\Python\\Python36-32\\python.exe C:\\test2.py output.txt 2>&1");

Même cela ne crée pas le fichier de sortie:

Process p = Runtime.getRuntime().exec("C:\\Python\\Python36-32\\python.exe C:\\test2.py");

Quel est le problème? P >


2 commentaires

Si vous tapez manuellement cette chaîne exacte en utilisant le programme shell de commande Windows cmd.exe , fait-il ce que vous attendez?


Oui, les deux déclarations donnent les résultats attendus.


3 Réponses :


1
votes

Je pense que vous pourriez tenter votre chance avec la classe ProcessBuilder.

Si je lis correctement la documentation Oracle, les entrées et sorties std sont dirigées vers les tubes par défaut mais ProcessBuilder a une méthode simple pour que vous puissiez explicitement définit la sortie (ou l'entrée) sur un fichier sur votre système ou autre .

Si vous voulez que votre programme Python utilise la même sortie que votre programme Java (probablement stdout et stderr), vous pouvez utiliser stg comme ceci:

ProcessBuilder pb = new ProcessBuilder("C:\\Python\\Python36-32\\python.exe", "C:\\test2.py");
pb.redirectOutput(Redirect.INHERIT);
Process p = pb.start();

p>


4 commentaires

J'obtiens cette erreur: java.io.IOException: Impossible d'exécuter le programme "C: \ Python \ Python36-32 \ python.exe C: \ test2.py": Erreur CreateProcess = 2, le système ne trouve pas le fichier spécifié à java.lang.ProcessBuilder.start (ProcessBuilder.java:1048) à RunninPythonFromJava.main (RunninPythonFromJava.java:16) Causé par: java.io.IOException: erreur CreateProcess = 2, le système ne trouve pas le fichier spécifié


Que diriez-vous de ceci: stackoverflow.com/a/40648879/9070798 ? Est-ce que cela résout votre problème?


Cela a fonctionné comme un charme - ProcessBuilder pb = new ProcessBuilder ("C: \\ Python \\ Python36-32 \\ python.exe", "C: \\ test2.py"); . Pour aller plus loin, comment puis-je transmettre les arguments à python et obtenir les données de retour?


Vous pouvez passer des arguments comme sur un terminal, en les ajoutant à votre ligne de commande dans votre code: ... new ProcessBuilder ("C: \ Python \\ Python36-32 \\ python.exe", "C : \\ test2.py "," arg0 "," arg1 "); Ou voulez-vous avoir une sorte d'interaction entre votre programme Java et votre programme Python? Dans ce cas, vous pouvez faire en sorte que votre programme Java écrive des éléments dans le flux d'entrée de votre processus python. Quant aux données de retour, je ne sais pas ce que vous faites. Une chose que vous pourriez faire est de faire en sorte que Java lise ce que votre programme python produit sur stdout, mais cela me semble assez ennuyeux.



0
votes

Une façon de démarrer un processus python consiste à utiliser un point d'entrée - test.cmd

public static void main(String[] args) throws IOException {
    try {
        Process p = Runtime.getRuntime().exec("test.cmd");
        p.waitFor();
        Scanner sc = new Scanner(p.getInputStream());
        while(sc.hasNextLine()){
            System.out.println(sc.nextLine());
        }
        sc.close();
    } catch (Exception err) {
        err.printStackTrace();
    }
}

voici hello.py

#!/usr/bin/env python3
import os
if not os.path.exists('dir'):
    os.makedirs('dir')

Ici est mon code Java:

echo Hello
python hello.py


0 commentaires

1
votes

Vous pouvez utiliser l'API ProcessBuilder, rediriger la sortie vers un fichier puis attendre le résultat.

print("Hello from python')

Le fichier python test.py contient une instruction d'impression simple:

Process p = Runtime.getRuntime().exec(PYTHON_PATH + " " + PATH_TO_SCRIPT);
p.waitFor();

byte[] buffer = new byte[1024];
byte[] errBuffer = new byte[1024];

p.getInputStream().read(buffer);
p.getErrorStream().read(errBuffer);

System.out.println(new String(buffer));
System.out.println(new String(errBuffer));

Je suppose que ce serait encore plus simple, si vous n'avez pas besoin d'attendre le résultat.

L'utilisation de l'API Process devrait également fonctionner.

Comme dans votre exemple (j'utilise les mêmes constantes déclarées ci-dessus):

print("Hello from python")

Pour voir la sortie de l'instruction print, vous devez attendre et rediriger les flux . Idem pour le flux d'erreurs.

Maintenant, si vous cassez le script python comme ceci:

public class Main {

    public static final String PYTHON_PATH = "D:\\Anaconda3\\python.exe";
    public static final String PATH_TO_SCRIPT = "D:\\projects\\StartScript\\test.py";

    public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder builder = new ProcessBuilder();
        builder.command(PYTHON_PATH, PATH_TO_SCRIPT);

        // Redirect output to a file
        builder.redirectOutput(new File("output.txt"));

        builder.start().waitFor();

        // Print output to console
        ProcessBuilder.Redirect output = builder.redirectOutput();
        File outputFile = output.file();
        BufferedReader br = new BufferedReader(new FileReader(outputFile));

        String st;
        while ((st = br.readLine()) != null) {
            System.out.println(st);
        }

    }
}

vous devriez également pouvoir voir l'erreur imprimée.


0 commentaires