Invoking Python from SonataFlow

This document describes how to integrate python scripts and functions into your workflow using SonataFlow custom functions. The code appearing in this document is copied from serverless-workflow-python-quarkus example application and PythonService integration test.

Enable Python support

To enable Python support, you must add the Python add-on dependency to your SonataFlow module pom.xml file

<dependency>
      <groupId>org.apache.kie.sonataflow</groupId>
      <artifactId>sonataflow-addons-quarkus-python</artifactId>
</dependency>

Invoking embedded Python script.

SonataFlow supports the execution of Python script in the same memory address as the running workflow.

To invoke a Python script the first step is to define a custom Python function at the beginning of the flow.

 "functions": [
    {
      "name": "python",
      "type": "custom",
      "operation": "script:python"
    }
  ]

Once done, you can use that function several times to execute arbitrary Python code. The Python code is provided as an argument of the function call through the script property.

"functionRef":
    "refName": "python",
    "arguments": {
      "script": "import numpy as np"
     }
 }

Previous snippet imports numpy library. The same Python function can be invoked again to generate an array containing three random numbers between 0 and 10.

"functionRef": {
   "refName": "python",
   "arguments": {
      "script": "rng = np.random.default_rng().integers(low=0,high=10,size=3)"
    }
  }

To access the result of the embedded python invocation, SonataFlow provides a special context variable: $WORKFLOW.python. Therefore, if you want to set the rng variable from the previous script as the output property of the workflow model, you write

"stateDataFilter" : {
  "output" : "{result:$WORKFLOW.python.rng}"
}

Invoking Python function.

You can also invoke functions from standard or custom python modules.

You must define a serverless workflow function definition that invokes the Python function. You should specify, within the operation property, the name of the Python module and function to be invoked when the function is called. You should separate the module name and the function name using :: and prefix them with services::python:

The following example defines a function that invokes a standard Python function math.factorial(x)

 "functions" : [ {
    "name" : "factorial",
    "operation" : "service:python:math::factorial",
    "type" : "custom"
  }

Once you have defined the function, you might call it passing the expected arguments. In the case of factorial, an integer stored in property x of the workflow model.

 "functionRef" : {
          "refName": "factorial",
          "arguments" : ".x"
       }

The return value of the function can be handled as any other function result using the actionDataFilter.toStateData Serverless Workflow construct. The following will set a workflow model property called result with the factorial invocation returned value.

  "actionDataFilter" : {
        "toStateData" : ".result"
      }

Further reading

The Openvino illustrates the powerful AI capabilities of integrating workflows with Python. It is a must-see for all interested in the topic.

Found an issue?

If you find an issue or any misleading information, please feel free to report it here. We really appreciate it!