Class GraalPyResources

java.lang.Object
org.graalvm.python.embedding.GraalPyResources

public final class GraalPyResources extends Object
This class provides utilities related to Python resources used in GraalPy embedding scenarios which can be of the following kind:
  • Python application files
  • Third-party Python packages

Resource files can be embedded and distributed in an application file or made available from an external directory.

Virtual Filesystem

If the resource files are part of an application file (jar file or a native image executable), then at runtime they will be accessed as standard Java resources through GraalPy VirtualFileSystem. This will be transparent to Python code running in GraalPy so that it can use standard Python IO to access those files.

In order to make this work, it is necessary for those embedded resources to have a common resource root directory. The default value is /org.graalvm.python.vfs, however the recommended convention is to use GRAALPY-VFS/{groupId}/{artifactId}. This root directory will then be in python code mapped to the virtual filesystem mount point, by default /graalpy_vfs. Refer to VirtualFileSystem.Builder.resourceDirectory(String) documentation for more details.

External Directory

As an alternative to Java resources with the Virtual Filesystem, it is also possible to configure the GraalPy context to use an external directory, which is not embedded as a Java resource into the resulting application. Python code will access the files directly from the real filesystem.

Conventions

The factory methods in GraalPyResources rely on the following conventions:

  • ${resources_root}/src: used for Python application files. This directory will be configured as the default search path for Python module files (equivalent to PYTHONPATH environment variable).
  • ${resources_root}/venv: used for the Python virtual environment holding installed third-party Python packages. The Context will be configured as if it is executed from this virtual environment. Notably packages installed in this virtual environment will be automatically available for importing.
where ${resources_root} is either the resource root /org.graalvm.python.vfs or an external directory.

Example creating a GraalPy context configured for the usage with a VirtualFileSystem:

VirtualFileSystem.Builder builder = VirtualFileSystem.newBuilder();
builder.unixMountPoint("/python-resources");
VirtualFileSystem vfs = builder.build();
try (Context context = GraalPyResources.contextBuilder(vfs).build()) {
        context.eval("python", "for line in open('/python-resources/data.txt').readlines(): print(line)");
} catch (PolyglotException e) {
        if (e.isExit()) {
                System.exit(e.getExitStatus());
        } else {
                throw e;
        }
}
In this example we:
  • create a VirtualFileSystem configured to have the root /python-resources
  • create a GraalPy context preconfigured with that VirtualFileSystem
  • use the context to invoke a python snippet reading a resource file

GraalPy context instances created by factory methods in this class are preconfigured with some particular resource paths:

  • ${resources_root}/venv - is reserved for a python virtual environment holding third-party packages. The context will be configured as if it were executed from this virtual environment. Notably packages installed in this virtual environment will be automatically available for importing.
  • ${resources_root}/src - is reserved for python application files - e.g. python sources. GraalPy context will be configured to see those files as if set in PYTHONPATH environment variable.
where ${resources_root} is either an external directory or the virtual filesystem resource root /org.graalvm.python.vfs.

Example creating a GraalPy context configured for the usage with an external resource directory:

try (Context context = GraalPyResources.contextBuilder(Path.of("python-resources")).build()) {
        context.eval("python", "import mymodule; mymodule.print_hello_world()");
} catch (PolyglotException e) {
        if (e.isExit()) {
                System.exit(e.getExitStatus());
        } else {
                throw e;
        }
}
In this example we:
  • create a GraalPy context which is preconfigured with GraalPy resources in an external resource directory
  • use the context to import the python module mymodule, which should be either located in python-resources/src or in a python package installed in python-resources/venv (python virtual environment)

For more examples on how to use this class refer to GraalPy Demos and Guides.

Since:
24.2.0
See Also:
  • Method Details

    • createContext

      public static org.graalvm.polyglot.Context createContext()
      Creates a GraalPy context preconfigured with a VirtualFileSystem and other GraalPy and polyglot Context configuration options optimized for the usage of the Python virtual environment contained in the virtual filesystem.

      Following resource paths are preconfigured:

      • /org.graalvm.python.vfs/venv - is set as the python virtual environment location
      • /org.graalvm.python.vfs/src - is set as the python sources location

      When the virtual filesystem is located in other than the default resource directory, org.graalvm.python.vfs, i.e., using Maven or Gradle option resourceDirectory, use contextBuilder(VirtualFileSystem) and VirtualFileSystem.Builder.resourceDirectory(String) when building the VirtualFileSystem.

      Returns:
      a new Context instance
      Since:
      24.2.0
    • contextBuilder

      public static org.graalvm.polyglot.Context.Builder contextBuilder()
      Creates a GraalPy context builder preconfigured with a VirtualFileSystem and other GraalPy and polyglot Context configuration options optimized for the usage of the Python virtual environment contained in the virtual filesystem.

      Following resource paths are preconfigured:

      • /org.graalvm.python.vfs/venv - is set as the python virtual environment location
      • /org.graalvm.python.vfs/src - is set as the python sources location

      Example creating a GraalPy context and overriding the verbose option.

      Context.Builder builder = GraalPyResources.contextBuilder().option("python.VerboseFlag", "true");
      try (Context context = builder.build()) {
              context.eval("python", "print('hello world')");
      } catch (PolyglotException e) {
              if (e.isExit()) {
                      System.exit(e.getExitStatus());
              } else {
                      throw e;
              }
      }
      

      When the virtual filesystem is located in other than the default resource directory, org.graalvm.python.vfs, i.e., using Maven or Gradle option resourceDirectory, use contextBuilder(VirtualFileSystem) and VirtualFileSystem.Builder.resourceDirectory(String) when building the VirtualFileSystem.

      Returns:
      a new Context.Builder instance
      Since:
      24.2.0
      See Also:
    • contextBuilder

      public static org.graalvm.polyglot.Context.Builder contextBuilder(VirtualFileSystem vfs)
      Creates a GraalPy context builder preconfigured with the given VirtualFileSystem and other GraalPy and polygot Context configuration options optimized for the usage of the Python virtual environment contained in the virtual filesystem.

      Following resource paths are preconfigured:

      • /org.graalvm.python.vfs/venv - is set as the python virtual environment location
      • /org.graalvm.python.vfs/src - is set as the python sources location

      Example creating a GraalPy context configured for the usage with a virtual FileSystem:

      VirtualFileSystem.Builder vfsBuilder = VirtualFileSystem.newBuilder();
      vfsBuilder.unixMountPoint("/python-resources");
      VirtualFileSystem vfs = vfsBuilder.build();
      Context.Builder ctxBuilder = GraalPyResources.contextBuilder(vfs);
      try (Context context = ctxBuilder.build()) {
              context.eval("python", "for line in open('/python-resources/data.txt').readlines(): print(line)");
      } catch (PolyglotException e) {
              if (e.isExit()) {
                      System.exit(e.getExitStatus());
              } else {
                      throw e;
              }
      }
      
      In this example we:
      • create a VirtualFileSystem configured to have the root /python-resources
      • create a GraalPy context preconfigured with that VirtualFileSystem
      • use the context to invoke a python snippet reading a resource file
      Parameters:
      vfs - the VirtualFileSystem to be used with the created Context
      Returns:
      a new Context.Builder instance
      Since:
      24.2.0
      See Also:
    • contextBuilder

      public static org.graalvm.polyglot.Context.Builder contextBuilder(Path externalResourcesDirectory)
      Creates a GraalPy context preconfigured with GraalPy and polyglot Context configuration options for use with resources located in an external directory in real filesystem.

      Following resource paths are preconfigured:

      • ${externalResourcesDirectory}/venv - is set as the python virtual environment location
      • ${externalResourcesDirectory}/src - is set as the python sources location

      Example

      Context.Builder builder = GraalPyResources.contextBuilder(Path.of("python-resources"));
      try (Context context = builder.build()) {
              context.eval("python", "import mymodule; mymodule.print_hello_world()");
      } catch (PolyglotException e) {
              if (e.isExit()) {
                      System.exit(e.getExitStatus());
              } else {
                      throw e;
              }
      }
      
      In this example we:
      • create a GraalPy context which is preconfigured with GraalPy resources in an external resource directory
      • use the context to import the python module mymodule, which should be either located in python-resources/src or in a python package installed in /python/venv (python virtual environment)
      • note that in this scenario, the Python context has access to the extracted resources as well as the rest of the real filesystem

      External resources directory is often used for better compatibility with Python native extensions that may bypass the Python abstractions and access the filesystem directly from native code. Setting the PosixModuleBackend option to "native" increases the compatibility further, but in such case even Python code bypasses the Truffle abstractions and accesses native POSIX APIs directly. Usage:

      GraalPyResources.contextBuilder(Path.of("python-resources")).option("python.PosixModuleBackend", "native")
      

      When Maven or Gradle GraalPy plugin is used to build the virtual environment, it also has to be configured to generate the virtual environment into the same directory using the <externalDirectory> tag in Maven or the externalDirectory field in Gradle.

      Parameters:
      externalResourcesDirectory - the root directory with GraalPy specific embedding resources
      Returns:
      a new Context.Builder instance
      Since:
      24.2.0
    • getNativeExecutablePath

      public static Path getNativeExecutablePath()
      Determines a native executable path if running in ImageInfo.inImageRuntimeCode().

      Example creating a GraalPy context preconfigured with an external resource directory located next to a native image executable.

      Path resourcesDir = GraalPyResources.getNativeExecutablePath().getParent().resolve("python-resources");
      try (Context context = GraalPyResources.contextBuilder(resourcesDir).build()) {
              context.eval("python", "print('hello world')");
      }
      
      Returns:
      the native executable path if it could be retrieved, otherwise null.
      Since:
      24.2.0
      See Also:
    • extractVirtualFileSystemResources

      public static void extractVirtualFileSystemResources(VirtualFileSystem vfs, Path externalResourcesDirectory) throws IOException
      Extract Python resources which are distributed as part of a jar file or a native image executable into a directory. This can be useful to manage and ship resources with the Maven workflow, but use them (cached) from the real filesystem for better compatibility.

      The structure of the created resource directory will stay the same like the embedded Python resources structure:

      • ${externalResourcesDirectory}/venv - the python virtual environment location
      • ${externalResourcesDirectory}/src - the python sources location

      Example

      Path resourcesDir = Path.of(System.getProperty("user.home"), ".cache", "my.java.python.app.resources");
      VirtualFileSystem vfs = VirtualFileSystem.newBuilder().build();
      GraalPyResources.extractVirtualFileSystemResources(vfs, resourcesDir);
      try (Context context = GraalPyResources.contextBuilder(resourcesDir).build()) {
              context.eval("python", "print('hello world')");
      }
      
      Parameters:
      vfs - the VirtualFileSystem from which resources are to be extracted
      externalResourcesDirectory - the target directory to extract the resources to
      Throws:
      IOException - if resources isn't a directory
      Since:
      24.2.0
      See Also: