From 2e5e679cea919297094d25ce37dada7e61b6f756 Mon Sep 17 00:00:00 2001 From: q Date: Sun, 11 Jan 2026 07:25:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A2=9E=E5=BC=BAPyContextPool=20Engine?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E7=9A=84=E5=85=BC=E5=AE=B9=E6=80=A7=E5=B9=B6?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0GraalPy=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qaiu/parser/custompy/PyContextPool.java | 134 ++++++++++++++---- .../test/java/cn/qaiu/parser/GraalPyTest.java | 57 ++++++++ 2 files changed, 166 insertions(+), 25 deletions(-) create mode 100644 parser/src/test/java/cn/qaiu/parser/GraalPyTest.java diff --git a/parser/src/main/java/cn/qaiu/parser/custompy/PyContextPool.java b/parser/src/main/java/cn/qaiu/parser/custompy/PyContextPool.java index e1bf7fa..2e97ffe 100644 --- a/parser/src/main/java/cn/qaiu/parser/custompy/PyContextPool.java +++ b/parser/src/main/java/cn/qaiu/parser/custompy/PyContextPool.java @@ -134,10 +134,30 @@ public class PyContextPool { private PyContextPool() { log.info("初始化GraalPy Context池..."); - // 创建共享Engine - this.sharedEngine = Engine.newBuilder() - .option("engine.WarnInterpreterOnly", "false") - .build(); + // 创建共享Engine - 优先使用 GraalPyResources + Engine engine = null; + try { + // 使用 GraalPyResources 创建,这是推荐的方式 + var tempContext = org.graalvm.python.embedding.GraalPyResources.contextBuilder() + .option("engine.WarnInterpreterOnly", "false") + .build(); + engine = tempContext.getEngine(); + tempContext.close(); + log.info("Engine创建成功(GraalPyResources模式)"); + } catch (Exception e) { + log.warn("GraalPyResources模式创建Engine失败,尝试标准方式: {}", e.getMessage()); + try { + engine = Engine.newBuilder() + .option("engine.WarnInterpreterOnly", "false") + .build(); + log.info("Engine创建成功(标准模式)"); + } catch (Exception e2) { + log.error("标准模式创建Engine也失败: {}", e2.getMessage()); + checkGraalPyAvailability(); + throw new RuntimeException("无法初始化GraalPy Engine,请确保GraalPy依赖正确配置", e2); + } + } + this.sharedEngine = engine; // 创建Context池 this.contextPool = new LinkedBlockingQueue<>(MAX_POOL_SIZE); @@ -234,27 +254,52 @@ public class PyContextPool { throw new IllegalStateException("Context池已关闭"); } - Context context = Context.newBuilder("python") - .engine(sharedEngine) - .allowHostAccess(HostAccess.newBuilder(HostAccess.EXPLICIT) - .allowArrayAccess(true) - .allowListAccess(true) - .allowMapAccess(true) - .allowIterableAccess(true) - .allowIteratorAccess(true) - .build()) - .allowHostClassLookup(className -> false) - .allowExperimentalOptions(true) - .allowCreateThread(true) - .allowNativeAccess(false) - .allowCreateProcess(false) - .allowIO(IOAccess.newBuilder() - .allowHostFileAccess(false) - .allowHostSocketAccess(false) - .build()) - .option("python.PythonHome", "") - .option("python.ForceImportSite", "false") - .build(); + Context context; + try { + // 首先尝试使用共享Engine创建 + context = Context.newBuilder("python") + .engine(sharedEngine) + .allowHostAccess(HostAccess.newBuilder(HostAccess.EXPLICIT) + .allowArrayAccess(true) + .allowListAccess(true) + .allowMapAccess(true) + .allowIterableAccess(true) + .allowIteratorAccess(true) + .build()) + .allowHostClassLookup(className -> false) + .allowExperimentalOptions(true) + .allowCreateThread(true) + .allowNativeAccess(false) + .allowCreateProcess(false) + .allowIO(IOAccess.newBuilder() + .allowHostFileAccess(false) + .allowHostSocketAccess(false) + .build()) + .option("python.PythonHome", "") + .option("python.ForceImportSite", "false") + .build(); + } catch (Exception e) { + log.warn("使用共享Engine创建Context失败,尝试使用GraalPyResources: {}", e.getMessage()); + // 使用 GraalPyResources 作为备选 + context = org.graalvm.python.embedding.GraalPyResources.contextBuilder() + .allowHostAccess(HostAccess.newBuilder(HostAccess.EXPLICIT) + .allowArrayAccess(true) + .allowListAccess(true) + .allowMapAccess(true) + .allowIterableAccess(true) + .allowIteratorAccess(true) + .build()) + .allowHostClassLookup(className -> false) + .allowExperimentalOptions(true) + .allowCreateThread(true) + .allowNativeAccess(false) + .allowCreateProcess(false) + .allowIO(IOAccess.newBuilder() + .allowHostFileAccess(false) + .allowHostSocketAccess(false) + .build()) + .build(); + } createdCount.incrementAndGet(); log.debug("创建新的GraalPy Context,当前总数: {}", createdCount.get()); @@ -421,6 +466,45 @@ public class PyContextPool { return createdCount.get(); } + /** + * 检查GraalPy是否可用 + */ + private void checkGraalPyAvailability() { + log.error("===== GraalPy 可用性检查 ====="); + + // 检查类路径 + try { + Class.forName("org.graalvm.polyglot.Engine"); + log.info("✓ org.graalvm.polyglot.Engine 类存在"); + } catch (ClassNotFoundException e) { + log.error("✗ org.graalvm.polyglot.Engine 类不存在"); + } + + try { + Class.forName("org.graalvm.python.embedding.GraalPyResources"); + log.info("✓ org.graalvm.python.embedding.GraalPyResources 类存在"); + } catch (ClassNotFoundException e) { + log.error("✗ org.graalvm.python.embedding.GraalPyResources 类不存在 - 缺少 python-embedding 依赖"); + } + + // 尝试列出可用语言 + try { + log.info("尝试使用 GraalPyResources 创建 Context..."); + var context = org.graalvm.python.embedding.GraalPyResources.createContext(); + log.info("✓ GraalPyResources 创建 Context 成功"); + context.close(); + } catch (Exception e) { + log.error("✗ GraalPyResources 创建 Context 失败: {}", e.getMessage()); + } + + log.error("================================"); + log.error("请检查以下依赖是否正确配置:"); + log.error(" 1. org.graalvm.polyglot:polyglot"); + log.error(" 2. org.graalvm.polyglot:python (type=pom)"); + log.error(" 3. org.graalvm.python:python-embedding"); + log.error("================================"); + } + /** * 关闭Context池 */ diff --git a/parser/src/test/java/cn/qaiu/parser/GraalPyTest.java b/parser/src/test/java/cn/qaiu/parser/GraalPyTest.java new file mode 100644 index 0000000..a16e69e --- /dev/null +++ b/parser/src/test/java/cn/qaiu/parser/GraalPyTest.java @@ -0,0 +1,57 @@ +package cn.qaiu.parser; + +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Engine; +import org.graalvm.polyglot.Value; + +/** + * GraalPy 简单测试 + */ +public class GraalPyTest { + + public static void main(String[] args) { + System.out.println("===== GraalPy 测试开始 ====="); + + try { + System.out.println("1. 检查可用语言..."); + try (Engine engine = Engine.create()) { + System.out.println(" 可用语言: " + engine.getLanguages().keySet()); + if (!engine.getLanguages().containsKey("python")) { + System.err.println(" ✗ Python 语言不可用!"); + System.exit(1); + } + System.out.println(" ✓ Python 语言可用"); + } + + System.out.println("2. 尝试创建 Python Context..."); + try (Context context = Context.newBuilder("python") + .option("engine.WarnInterpreterOnly", "false") + .build()) { + System.out.println(" ✓ Context 创建成功"); + + System.out.println("3. 执行简单 Python 代码..."); + Value result = context.eval("python", "1 + 2"); + System.out.println(" ✓ 计算结果: 1 + 2 = " + result.asInt()); + + System.out.println("4. 执行字符串操作..."); + Value strResult = context.eval("python", "'Hello' + ' ' + 'GraalPy'"); + System.out.println(" ✓ 字符串结果: " + strResult.asString()); + + System.out.println("5. 执行多行代码..."); + String code = """ + def greet(name): + return f"Hello, {name}!" + greet("World") + """; + Value funcResult = context.eval("python", code); + System.out.println(" ✓ 函数结果: " + funcResult.asString()); + } + + System.out.println("===== GraalPy 测试通过 ====="); + } catch (Exception e) { + System.err.println("✗ GraalPy 测试失败: " + e.getMessage()); + e.printStackTrace(); + System.exit(1); + } + } +}