#Python 言語には豊富なシステム管理、データ処理、統計ソフトウェア パッケージがあるため、Java アプリケーションから Python コードを呼び出す必要は非常に一般的であり、実際的です。 DataX は、Alibaba がオープンソース化した異種データ ソース用のオフライン同期ツールで、リレーショナル データベース (MySQL、Oracle など)、HDFS、Hive、ODPS、HBase、FTP を含むさまざまな異種データ ソース間で安定した効率的なデータを実現することに特化しています。 、などの同期機能。 Datax は Java を通じて Python スクリプトも呼び出します。
Java は、ProcessBuilder API と JSR-223 Scripting Engine という 2 つのメソッドを提供します。
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 オブジェクトを取得した後、出力ストリームを読み取って結果を確認します。
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('Hello Python!')"); 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 サイトの他の関連記事を参照してください。