
在某些场景下,我们可能需要利用java程序的强大生态系统来调用python脚本,以利用python在特定领域的优势,例如数据处理、机器学习或系统硬件交互。java提供了processbuilder类来执行外部系统命令,从而实现与python脚本的交互。然而,这种跨语言调用并非没有挑战,其中最常见的问题之一就是执行失败并返回特定的错误码。
当Java通过ProcessBuilder调用Python脚本时,如果进程退出并返回错误码9009,这通常意味着操作系统无法找到你尝试执行的命令或文件。在Windows系统中,这类似于在命令行中输入一个不存在的命令;在Linux/macOS中,则可能是command not found。具体到Java调用Python的场景,9009错误通常指向以下两个核心问题:
为了避免9009错误并确保Java成功调用Python脚本,我们需要关注以下几个关键点:
确保Java能够正确找到Python解释器是首要任务。
同样,Python脚本的路径也应尽可能明确。
立即学习“Java免费学习笔记(深入)”;
Python脚本通常会依赖第三方库。当Java调用Python时,确保这些库已安装在被调用的Python解释器环境中至关重要。
当外部进程执行时,其标准输出(stdout)和标准错误(stderr)是获取执行结果和诊断问题的关键。
基于原始问题中的代码,我们可以进行以下优化和改进,以提高健壮性和可诊断性。
为了让Java更方便地解析结果,Python脚本应该只输出最关键的信息,例如一个布尔值,并确保错误信息输出到标准错误流。
import sys
import usbmonitor
from usbmonitor.attributes import ID_MODEL, ID_MODEL_ID, ID_VENDOR_ID
# 目标设备ID
LOOK_FOR_DEVICE_ID = "USB\VID_058F&PID_9540\5&54725E2&0&2"
def is_usb_device_connected(target_id):
"""
检查特定USB设备是否连接。
将错误信息输出到sys.stderr,正常结果输出到sys.stdout。
"""
try:
monitor = usbmonitor.USBMonitor()
devices_dict = monitor.get_available_devices()
for device_id, device_info in devices_dict.items():
# 简化比较逻辑,只比较VID和PID部分
# 注意:原始逻辑是 split('\')[1],这可能不完全匹配VID_PID
# 如果需要精确匹配,应调整匹配逻辑
if target_id.split('\')[1] == device_id.split('\')[1]:
return True
return False
except Exception as e:
# 将任何运行时错误输出到标准错误流
print(f"Python script error: {e}", file=sys.stderr)
return False # 发生错误时返回False
if __name__ == "__main__":
# 仅将最终的布尔结果打印到标准输出
result = is_usb_device_connected(LOOK_FOR_DEVICE_ID)
print(str(result)) # 输出 'True' 或 'False' 字符串
# 根据结果设置退出码,0表示成功,非0表示失败或未找到
sys.exit(0 if result else 1)
Python脚本改进说明:
Java代码需要正确构建ProcessBuilder,处理Python的输出和错误流,并等待进程完成。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.io.File;
public class UsbDeviceChecker {
public boolean isUsbDeviceConnected() {
Process process = null;
boolean isConnected = false; // 默认未连接
try {
// 1. 指定Python解释器的绝对路径。
// 示例:Windows用户可能需要 "C:\Python311\python.exe"
// Linux/macOS用户可能需要 "/usr/bin/python3" 或 "/usr/local/bin/python3"
String pythonInterpreter = "python3"; // 如果python3在PATH中,可这样使用
// 否则,使用绝对路径:
// String pythonInterpreter = "C:\Users\YourUser\AppData\Local\Programs\Python\Python311\python.exe";
// 2. 指定Python脚本的绝对路径。
String scriptPath = "C:\CS IA\src\java\findUSB.py";
File scriptFile = new File(scriptPath);
// 检查脚本文件是否存在
if (!scriptFile.exists()) {
System.err.println("Error: Python script not found at " + scriptPath);
return false;
}
ProcessBuilder processBuilder = new ProcessBuilder(pythonInterpreter, scriptPath);
// 可以设置工作目录,如果Python脚本需要访问相对路径文件
// processBuilder.directory(new File("C:\CS IA\src\java\"));
// 启动进程
process = processBuilder.start();
// 异步读取标准输出和标准错误流,避免阻塞
// 使用try-with-resources确保流被正确关闭
try (BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
// 创建线程来异步读取标准错误流,防止进程阻塞
Future<Void> stderrFuture = Executors.newSingleThreadExecutor().submit(() -> {
String line;
try {
while ((line = stderrReader.readLine()) != null) {
System.err.println("Python stderr: " + line);
}
} catch (IOException e) {
System.err.println("Error reading Python stderr: " + e.getMessage());
}
return null;
});
// 读取标准输出流
String line;
while ((line = stdoutReader.readLine()) != null) {
System.out.println("Python stdout: " + line); // 打印所有输出用于调试
// 假设Python脚本最后一行输出的是布尔值 "True" 或 "False"
if (line.trim().equalsIgnoreCase("true") || line.trim().equalsIgnoreCase("false")) {
isConnected = Boolean.parseBoolean(line.trim());
}
}
// 等待标准错误流读取完成
stderrFuture.get(5, TimeUnit.SECONDS); // 最多等待5秒
} // try-with-resources 会自动关闭 reader
// 等待Python进程执行完毕并获取退出码
int exitCode = process.waitFor();
System.out.println("Python script exited with code: " + exitCode);
// 根据Python脚本的输出和退出码判断结果
if (exitCode == 0) { // 约定退出码0表示Python脚本执行成功
if (isConnected) {
System.out.println("The USB device is connected.");
return true;
} else {
System.out.println("The USB device is NOT connected.");
return false;
}
} else {
System.err.println("Python script execution failed or device not found (exit code: " + exitCode + ").");
return false;
}
} catch (IOException | InterruptedException e) {
System.err.println("Error during Python script execution: " + e.getMessage());
e.printStackTrace();
return false;
} catch (Exception e) { // 捕获其他可能的异常,如 Future.get() 的异常
System.err.println("An unexpected error occurred: " + e.getMessage());
e.printStackTrace();
return false;
} finally {
if (process != null) {
// 销毁进程,释放系统资源。对于已完成的进程,这可能没有立即效果,
// 但对于未正常退出的进程,确保其被终止。
process.destroy();
}
}
}
public static void main(String[] args) {
UsbDeviceChecker checker = new UsbDeviceChecker();
if (checker.isUsbDeviceConnected()) {
System.out.println("Final Check Result: USB device is connected.");
} else {
System.out.println("Final Check Result: USB device is NOT connected.");
}
}
}Java代码改进说明:
以上就是Java调用Python脚本:解决9009错误及最佳实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号