Maison  >  Article  >  Java  >  Comment appeler Python en Java

Comment appeler Python en Java

WBOY
WBOYavant
2023-05-17 12:08:122221parcourir

    Le langage Python regorge de logiciels de gestion de système, de traitement de données et de statistiques, il est donc très nécessaire d'appeler du code Python à partir d'applications Java. commun et pratique. DataX est un outil de synchronisation hors ligne pour sources de données hétérogènes open source par Alibaba. Il est dédié à l'obtention de données stables et efficaces entre diverses sources de données hétérogènes, notamment les bases de données relationnelles (MySQL, Oracle, etc.), HDFS, Hive, ODPS, HBase, FTP. , etc. Fonction de synchronisation. Datax appelle également des scripts Python via Java.

    Java core

    Java fournit deux méthodes, à savoir l'API ProcessBuilder et le moteur de script JSR-223.

    Utilisez ProcessBuilder

    Créez un processus de système d'exploitation local via ProcessBuilder pour démarrer Python et exécuter le script Python. Le script hello.py affiche simplement "Bonjour Python !". L'environnement de développement doit avoir python installé et des variables d'environnement définies.

    @Test
    public void givenPythonScript_whenPythonProcessInvoked_thenSuccess() throws Exception {
        ProcessBuilder processBuilder = new ProcessBuilder("python", resolvePythonScriptPath("hello.py"));
        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();
        List<String> results = readProcessOutput(process.getInputStream());
        assertThat("Results should not be empty", results, is(not(empty())));
        assertThat("Results should contain output of script: ", results, hasItem(containsString("Hello Python!")));
        int exitCode = process.waitFor();
        assertEquals("No errors should be detected", 0, exitCode);
    }
    private List<String> readProcessOutput(InputStream inputStream) throws IOException {
        try (BufferedReader output = new BufferedReader(new InputStreamReader(inputStream))) {
            return output.lines()
                .collect(Collectors.toList());
        }
    }
    private String resolvePythonScriptPath(String filename) {
        File file = new File("src/test/resources/" + filename);
        return file.getAbsolutePath();
    }

    Pour réécrire cette phrase, tu peux dire : Commencez à utiliser la commande Python avec un argument, qui est le chemin complet du script Python. Il peut être placé dans le répertoire des ressources du projet Java. Ce qu'il faut noter est : redirectErrorStream(true), afin de fusionner le flux de sortie d'erreur dans le flux de sortie standard lorsqu'une erreur se produit lors de l'exécution du script. Les informations sur les erreurs peuvent être lues en appelant la méthode getInputStream() de l'objet Process. Sans ce paramètre, vous devez utiliser deux méthodes pour obtenir le flux : getInputStream() et getErrorStream(). Après avoir obtenu l'objet Process de ProcessBuilder, vérifiez les résultats en lisant le flux de sortie.

    Utilisation du moteur Java Script

    La spécification JSR-223 a été introduite pour la première fois dans Java 6, qui définit un ensemble d'API de script pouvant fournir des fonctionnalités de script de base. Ces API fournissent des mécanismes de partage de valeurs et d'exécution de scripts entre Java et les langages de script. L'objectif principal de cette spécification est d'unifier l'interaction entre Java et les langages de script dynamiques qui implémentent différentes JVM. Jython est une implémentation Java de Python qui s'exécute sur la JVM. En supposant que nous ayons Jython sur le CLASSPATH, le framework découvre automatiquement que nous avons la possibilité d'utiliser ce moteur de script et nous permet de demander directement le moteur de script Python. Dans Maven, on peut référencer Jython, ou le télécharger et l'installer directement

    <dependency>
        <groupId>org.python</groupId>
        <artifactId>jython</artifactId>
        <version>2.7.2</version>
    </dependency>

    Vous pouvez lister tous les moteurs de script supportés grâce au code suivant :

    public static void listEngines() {
        ScriptEngineManager manager = new ScriptEngineManager();
        List<ScriptEngineFactory> engines = manager.getEngineFactories();
        for (ScriptEngineFactory engine : engines) {
            LOGGER.info("Engine name: {}", engine.getEngineName());
            LOGGER.info("Version: {}", engine.getEngineVersion());
            LOGGER.info("Language: {}", engine.getLanguageName());
            LOGGER.info("Short Names:");
            for (String names : engine.getNames()) {
                LOGGER.info(names);
            }
        }
    }

    Si Jython est dans l'environnement disponible, vous devriez voir la sortie correspondante :

    ...
    Nom du moteur : jython
    Version : 2.7.2
    Langue : python#🎜 🎜#Noms courts :
    python
    jython

    Utilisez maintenant Jython pour appeler le script hello.py :

    @Test
    public void givenPythonScriptEngineIsAvailable_whenScriptInvoked_thenOutputDisplayed() throws Exception {
        StringWriter writer = new StringWriter();
        ScriptContext context = new SimpleScriptContext();
        context.setWriter(writer);
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("python");
        engine.eval(new FileReader(resolvePythonScriptPath("hello.py")), context);
        assertEquals("Should contain script output: ", "Hello Python!", writer.toString().trim());
    }

    Utilisez cette API que ci-dessus L'exemple est plus concis. Lors de la définition de ScriptContext, vous devez inclure un StringWriter afin d'enregistrer la sortie de l'exécution du script. Fournissez ensuite le nom court pour permettre à ScriptEngineManager de trouver le moteur de script, qui peut utiliser Python ou Jython. Enfin, vérifiez que le résultat est conforme aux attentes.

    En fait, vous pouvez également utiliser la classe PythonInterpretor pour appeler directement le code python intégré :

    @Test
    public void givenPythonInterpreter_whenPrintExecuted_thenOutputDisplayed() {
        try (PythonInterpreter pyInterp = new PythonInterpreter()) {
            StringWriter output = new StringWriter();
            pyInterp.setOut(output);
            pyInterp.exec("print(&#39;Hello Python!&#39;)");
            assertEquals("Should contain script output: ", "Hello Python!", output.toString().trim());
        }
    }

    La méthode exec fournie par la classe PythonInterpreter peut exécuter directement le code Python. Capturez le résultat de l'exécution via un StringWriter comme dans l'exemple précédent. Regardons un autre exemple :

    @Test
    public void givenPythonInterpreter_whenNumbersAdded_thenOutputDisplayed() {
        try (PythonInterpreter pyInterp = new PythonInterpreter()) {
            pyInterp.exec("x = 10+10");
            PyObject x = pyInterp.get("x");
            assertEquals("x: ", 20, x.asInt());
        }
    }

    L'exemple ci-dessus peut utiliser la méthode get pour accéder à la valeur de la variable. L'exemple suivant montre comment détecter les erreurs :

    try (PythonInterpreter pyInterp = new PythonInterpreter()) {
        pyInterp.exec("import syds");
    }

    L'exécution du code ci-dessus lèvera une exception PyException, ce qui revient à exécuter le script Python localement pour générer une erreur.

    Voici quelques points à noter :

    • PythonIntepreter implémente AutoCloseable et est mieux utilisé avec try-with-resources.

    • Le nom de la classe PythonIntepreter n'est pas un analyseur représentant le code Python exécuté en Jython dans jvm et doit être compilé en bytecode Java avant exécution.

    • Bien que Jython soit une implémentation Python de Java, il peut ne pas contenir tous les mêmes sous-packages que Python natif.

    L'exemple suivant montre comment attribuer des variables Java aux variables Python :

    import org.python.util.PythonInterpreter; 
    import org.python.core.*; 
    class test3{
        public static void main(String a[]){
            int number1 = 10;
            int number2 = 32;
            try (PythonInterpreter pyInterp = new PythonInterpreter()) {
                python.set("number1", new PyInteger(number1));
                python.set("number2", new PyInteger(number2));
                python.exec("number3 = number1+number2");
                PyObject number3 = python.get("number3");
                System.out.println("val : "+number3.toString());
            }
        }
    }

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer