嵌入式GraalPython脚本无法导入本地Python文件如何解决
GraalPython在JVM环境导入本地Python脚本问题解决
GraalPython完全支持在执行脚本时导入同项目下的其他本地Python脚本,你抛出的ModuleNotFoundError: No module named 'common'是Python模块搜索路径配置缺失导致的,不是功能限制。
你当前的实现直接加载单文件pyScripts/common/MyPyScript.py执行,默认配置下GraalPython不会自动把脚本的上级目录、项目脚本根目录加入sys.path搜索列表,Python解释器自然找不到common这个包。
可行解决方案
方案1:Context构建阶段配置模块搜索根目录(推荐)
不需要修改Python侧业务代码,直接在Scala侧创建Context时增加python.PythonPath配置,把Python脚本的存放根目录加入搜索路径:val context = Context.newBuilder("python") .allowAllAccess(true) .option("python.ForceImportSite", "true") .option("python.Executable", "pyScripts/venv/bin/graalpython") // 配置Python模块搜索根目录,多个路径用:分隔(Windows环境用;) .option("python.PythonPath", new File("pyScripts").getAbsolutePath) .build()配置完成后原脚本里的
from common.ScriptBase import ScriptBase可以正常导入。方案2:Python入口脚本内动态追加搜索路径
如果不方便调整JVM侧Context配置,直接在入口Python脚本的最开头手动把项目根目录加入sys.path:import sys import os # 当前脚本在pyScripts/common/下,取两次父目录得到脚本根目录pyScripts project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(project_root) import java import polyglot from common.ScriptBase import ScriptBase class MyPyScript(ScriptBase): # 业务逻辑 pass方案3:执行业务脚本前注入路径配置
既不想改JVM侧Context全局配置,也不想改业务Python脚本的话,可以在eval业务脚本前先执行一段初始化代码设置路径:// 初始化搜索路径 val initCode = s"import sys; sys.path.append('${new File("pyScripts").getAbsolutePath}')" context.eval(Source.newBuilder("python", initCode, "path_init.py").build()) // 加载执行业务脚本 val source = Source.newBuilder("python", new File("pyScripts/common/MyPyScript.py")).build() context.eval(source)
配置注意点
- 确保
common目录下存在空的__init__.py文件,Python(包括GraalPython)才会将该目录识别为可导入的正式包。 - 所有路径尽量传绝对路径,避免JVM进程工作目录和预期不一致导致的路径匹配失败。
- 如果需要保留虚拟环境内的三方包导入能力,配置
python.PythonPath时不要覆盖默认路径,可以在自定义路径后拼接原有sys.path的内容。
内容的提问来源于stack exchange,提问作者Allan
相关产品推荐
相关产品推荐

