ホームページ  >  記事  >  Java  >  JavaでPythonを呼び出す方法

JavaでPythonを呼び出す方法

WBOY
WBOY転載
2023-05-17 12:08:122221ブラウズ

    #Python 言語には豊富なシステム管理、データ処理、統計ソフトウェア パッケージがあるため、Java アプリケーションから Python コードを呼び出す必要は非常に一般的であり、実際的です。 DataX は、Alibaba がオープンソース化した異種データ ソース用のオフライン同期ツールで、リレーショナル データベース (MySQL、Oracle など)、HDFS、Hive、ODPS、HBase、FTP を含むさまざまな異種データ ソース間で安定した効率的なデータを実現することに特化しています。 、などの同期機能。 Datax は Java を通じて Python スクリプトも呼び出します。

    Java コア

    Java は、ProcessBuilder API と JSR-223 Scripting Engine という 2 つのメソッドを提供します。

    ProcessBuilder を使用する

    ProcessBuilder を使用してローカル オペレーティング システム プロセスを作成し、Python を起動し、Python スクリプトを実行します。hello.py スクリプトは単に「Hello Python!」を出力します。開発環境には Python がインストールされ、環境変数が設定されている必要があります。

    @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();
    }

    この文を書き直すと、次のように言えます。 Python コマンドを 1 つの引数 (Python スクリプトへの完全パス) とともに使用して開始します。 Java プロジェクトのリソース ディレクトリに配置できます。注意が必要なのは、スクリプト実行時にエラーが発生した場合に、エラー出力ストリームを標準出力ストリームにマージさせるための redirectErrorStream(true) です。エラー情報は、ProcessオブジェクトのgetInputStream()メソッドを呼び出すことで取得できます。この設定を行わない場合、ストリームを取得するために getInputStream() と getErrorStream() という 2 つのメソッドを使用する必要があります。 ProcessBuilder から Process オブジェクトを取得した後、出力ストリームを読み取って結果を確認します。

    Java Script Engine の使用

    JSR-223 仕様は Java 6 で初めて導入されました。この仕様は、基本的なスクリプト機能を提供できる一連のスクリプト API を定義します。これらの API は、Java とスクリプト言語の間で値を共有し、スクリプトを実行するためのメカニズムを提供します。この仕様の主な目的は、Java と、異なる JVM を実装する動的スクリプト言語の間の対話を統合することです。Jython は、JVM 上で実行される Python の Java 実装です。 CLASSPATH に Jython があると仮定すると、フレームワークはそのスクリプト エンジンを使用できる可能性があることを自動的に検出し、Python スクリプト エンジンを直接リクエストできるようになります。 Maven では、Jython を参照することも、Jython を直接ダウンロードしてインストールすることもできます。

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

    次のコードを使用して、サポートされているすべてのスクリプト エンジンを一覧表示できます。

    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);
            }
        }
    }

    環境で Jython が利用可能な場合は、次のことを行う必要があります。対応する出力を参照してください:

    ...
    エンジン名: jython
    バージョン: 2.7.2
    言語: python
    短い名前:
    python
    jython

    次に、Jython を使用して 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());
    }

    この API の使用方法は、上記の例よりも簡潔です。 ScriptContext を設定するときは、スクリプト実行の出力を保存するために StringWriter を含める必要があります。次に、Python または jython を使用できるスクリプト エンジンを見つけるために、ScriptEngineManager の短い名前を指定します。最後に、出力が期待どおりであることを確認します。

    実際、PythonInterpretor クラスを使用して、埋め込み Python コードを直接呼び出すこともできます。

    @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());
        }
    }

    PythonInterpreter クラスによって提供される exec メソッドは、Python コードを直接実行できます。前の例と同様に、StringWriter を介して実行出力をキャプチャします。別の例を見てみましょう:

    @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());
        }
    }

    上の例では、get メソッドを使用して変数値にアクセスできます。次の例は、エラーをキャッチする方法を示しています。

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

    上記のコードを実行すると、PyException 例外がスローされます。これは、Python スクリプトをローカルで実行してエラーを出力するのと同じです。

    ここで注意すべき点がいくつかあります:

    • PythonInterpreter は AutoCloseable を実装しており、try-with-resources と併用するのが最適です。

    • PythonInterpreter クラス名は、Python コードを表すパーサーではありません。Python プログラムは、jvm の Jython で実行され、実行前に Java バイトコードにコンパイルする必要があります。

    • Jython は Java の Python 実装ですが、ネイティブ Python と同じサブパッケージがすべて含まれているわけではありません。

    次の例は、Java 変数を Python 変数に割り当てる方法を示しています。

    以上がJavaでPythonを呼び出す方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。