嵌入式构建工具

GraalPy MavenGradle 插件提供了管理 Python 相关资源的功能,这些资源是将 Python 代码嵌入基于 Java 的应用程序所需的。

  • 用户提供的 Python 应用程序文件,例如项目中包含的 Python 源代码。
  • 插件在构建过程中根据插件配置安装的第三方 Python 包
  • Python 标准库,这是使 Native Image 生成的可执行文件自包含所必需的。

除了物理管理和部署这些文件之外,还需要在运行时通过相应的配置使它们在 Python 中可用 GraalPy 上下文 在你的 Java 代码中。该 GraalPyResources API 提供工厂方法来创建一个预配置用于访问 Python 的上下文,将相关资源嵌入 虚拟文件系统 或从专用 外部目录.

部署 #

有两种模式可以部署资源:使用虚拟文件系统将资源作为 Java 资源嵌入,或作为外部目录。

虚拟文件系统 #

Python 相关资源作为标准 Java 资源嵌入到应用程序文件中,无论是 JAR 还是 Native Image 生成的可执行文件。GraalPy 虚拟文件系统访问资源文件作为标准 Java 资源,并使它们可供在 GraalPy 中运行的 Python 代码使用。这对 Python 代码来说是透明的,它可以使用标准 Python IO 来访问这些文件。

Maven 或 Gradle 项目中的 Java 资源文件通常位于专用的资源目录中。所有名为 org.graalvm.python.vfs 的资源子目录将合并并映射到 Python 端的可配置虚拟文件系统挂载点,默认情况下为 /graalpy_vfs。例如,具有实际文件系统路径 ${project_resources_directory}/org.graalvm.python.vfs/src/foo/bar.py 的 Python 文件将在 Python 中作为 /graalpy_vfs/src/foo/bar.py 访问。

使用以下 GraalPyResources 工厂方法来创建预配置为使用虚拟文件系统的 GraalPy 上下文

  • GraalPyResources.createContext()
  • GraalPyResources.contextBuilder()
  • GraalPyResources.contextBuilder(VirtualFileSystem)

外部目录 #

作为使用虚拟文件系统的 Java 资源的替代方法,还可以配置 Maven 或 Gradle 插件来管理外部目录的内容,这些内容 不会 作为 Java 资源嵌入到生成的应用程序中。然后,用户负责部署此类目录。Python 代码将直接从实际文件系统访问文件。

使用以下 GraalPyResources 工厂方法来创建预配置为使用外部目录的 GraalPy 上下文

  • GraalPyResources.createContextBuilder(Path)

约定 #

中的工厂方法 GraalPyResources 依赖于以下约定,其中 ${root} 是外部目录或 Python 端的虚拟系统挂载点,在实际文件系统上为 ${project_resources_directory}/org.graalvm.python.vfs

  • ${root}/src:用于 Python 应用程序文件。此目录将配置为 Python 模块文件的默认搜索路径(等效于 PYTHONPATH 环境变量)。
  • ${root}/venv:用于包含已安装的第三方 Python 包的 Python 虚拟环境。上下文将配置为好像它从该虚拟环境执行一样。值得注意的是,在此虚拟环境中安装的包将自动可供导入。
  • ${root}/home:用于 Python 标准库(等效于 PYTHONHOME 环境变量)。

Maven 或 Gradle 插件将完全管理 venvhome 子目录的内容。对这些目录的任何手动更改将在构建过程中被插件覆盖。

  • ${root}/venv:插件根据 pom.xmlbuild.gradle 中的插件配置创建一个虚拟环境并安装所需的包。
  • ${root}/home:插件将 Python 标准库的所需部分(也可以配置)复制到此目录中。默认情况下,使用完整的标准库。

src 子目录由用户手动填充自定义 Python 脚本或模块。

GraalPy Maven 插件配置 #

pom.xml 文件中 graalpy-maven-pluginconfiguration 块中添加插件配置

<plugin>
    <groupId>org.graalvm.python</groupId>
    <artifactId>graalpy-maven-plugin</artifactId>
    ...
    <configuration>
        ...
    </configuration>
    ...
</plugin>

packages 元素声明一个第三方 Python 包列表,这些包将由插件下载和安装。

  • Python 包及其版本按使用 pip 的方式指定
    <configuration>
        <packages>
            <package>termcolor==2.2</package>
            ...
        </packages>
        ...
    </configuration>
    
  • pythonHome 子部分声明应部署标准库的哪些部分。

    每个 includeexclude 元素都解释为一个类似 Java 的正则表达式,指定应包含或排除哪些文件路径。

    <configuration>
        <pythonHome>
            <includes>
                <include>.*</include>
                ...
            </includes>
            <excludes>
                <exclude></exclude>
                ...
            </excludes>
        </pythonHome>
        ...
    </configuration>
    
  • 如果指定了 pythonResourcesDirectory 元素,则给定目录将用作 外部目录 并且不会嵌入任何 Java 资源。请记住使用适当的 GraalPyResources API 来创建上下文。
    <configuration>
        <pythonResourcesDirectory>${basedir}/python-resources</pythonResourcesDirectory>
        ...
    </configuration>
    

GraalPy Gradle 插件配置 #

注意:GraalPy Gradle 插件将在 GraalPy 版本 24.1.1(计划于 2024 年 10 月 15 日发布)起可用。

build.gradle 文件中的 GraalPy 块中添加插件配置。packages 元素声明一个第三方 Python 包列表,这些包将由插件下载和安装。

  • Python 包及其版本按使用 pip 的方式指定。
    graalPy {
      packages = ["termcolor==2.2"]
      ...
    }
    
  • pythonHome 子部分声明应部署标准库的哪些部分。

    includesexcludes 列表中的每个元素都解释为一个类似 Java 的正则表达式,指定应包含或排除哪些文件路径。

    graalPy {
      pythonHome {
        includes = [".*"]
        excludes = []
      }
      ...
    }
    
  • 如果指定了 pythonResourcesDirectory 元素,则给定目录将用作 外部目录 并且不会嵌入任何 Java 资源。请记住使用适当的 GraalPyResources API 来创建上下文。
    graalPy {
      pythonResourcesDirectory = file("$rootDir/python-resources")
      ...
    }
    

与我们联系