如何在Scala中调用Python脚本并获取输出?
Got it, let's fix this! The issue with your current code is that the ! method on a ProcessBuilder only returns the exit status code of the process, not the actual output from your Python script. Here are a few straightforward ways to capture that output in Scala:
1. Use the !! method (simplest approach)
The !! method executes the command and returns the entire standard output as a String. It's the quickest way if you just need the output and don't need to handle error streams separately:
import scala.sys.process._ // Execute the script and capture output val output = "python3 runner.py" !! // Print the captured output println(output) // Will print "testing"
Note: If the Python script exits with a non-zero status code, !! will throw an exception. If you want to handle this gracefully, you can use the overloaded version that takes a ProcessLogger to capture errors.
2. Use ProcessIO for fine-grained control
If you need to separate standard output and error output, or handle large streams without buffering everything into memory, use ProcessIO:
import scala.sys.process._ val stdout = new StringBuilder val stderr = new StringBuilder // Execute the script and capture both streams val exitCode = "python3 runner.py" ! ProcessIO( in => in.close(), // We don't need to send input to the Python script out => { // Read standard output line by line scala.io.Source.fromInputStream(out).getLines().foreach(line => stdout.append(line + "\n")) out.close() }, err => { // Read error output line by line scala.io.Source.fromInputStream(err).getLines().foreach(line => stderr.append(line + "\n")) err.close() } ) // Print results println(s"Exit Code: $exitCode") println(s"Standard Output:\n$stdout") println(s"Error Output:\n$stderr")
3. Use Java's ProcessBuilder with Scala's Source
You can also combine Java's low-level ProcessBuilder with Scala's Source to read the output:
import scala.io.Source // Start the Python process val process = new ProcessBuilder("python3", "runner.py").start() // Read standard output val output = Source.fromInputStream(process.getInputStream).mkString // Wait for the process to finish and get exit code val exitCode = process.waitFor() // Print results println(s"Exit Code: $exitCode") println(s"Output: $output")
This approach gives you full control over the process lifecycle, which is useful for more complex scenarios.
Quick Notes:
- Make sure
runner.pyis in your working directory, or use the full path to the script (e.g.,/home/user/scripts/runner.py). - If your output includes non-ASCII characters, specify the encoding when reading the stream (e.g.,
Source.fromInputStream(out, "UTF-8")).
内容的提问来源于stack exchange,提问作者user15609698

