Using the Python Assembly in Development

The Python assembly is used to execute functions in the Python language, to get results of their work, and to further work with the obtained data. Depending on where modules are located and how Python functions are implemented, the following methods can be used:

Executing Python Functions

The Python.Invoke static method is used if Python modules are located:

The Python.InvokeModule static method is used if Python modules are added to repository as the Python Module objects. It is necessary to create any additional objects to execute Python functions.

A Python function:

def summXY(x, y):

return x + y

For example, the Fore code implemented using Python.Invoke:

Var
    Result: Variant;
Begin
    Result := Python.Invoke("sample""summXY"100500);

If Python modules are located in any different folder, execute the following actions to use Python functions in code:

  1. Create an instance of the PythonUtils class, cast the obtained object to the IPythonUtils type.

  2. Use the IPythonUtils.AddFolderToPythonPath method to create a list of folders, in which Python modules and functions are searched.

  3. Execute the Python function using the IPythonUtils.Invoke method and get result.

Suppose that the summXY function specified above is implemented in the sample.py module, the module is located in the D:\Work\Python\ folder. The following code will execute the summXY function with the specified parameters values:

Var
    pUtils: IPythonUtils;
    Result: Variant;
Begin
    pUtils := 
New PythonUtils.Create;
    pUtils.AddFolderToPythonPath(
"d:\Work\Python\");
    Result := pUtils.Invoke("sample""summXY"100500);

Executing Python Functions Implemented in Class

To execute Python functions implemented in class, execute the following actions in the code:

  1. Create an instance of the PythonClassObject class, cast the obtained object to the IPythonClassObject type.

  2. Use the IPythonClassObject.GetAttr or IPythonClassObject.SetAttr method to get or change class attribute values if function execution result will depend on them.

  3. Execute function of the Python class using the IPythonClassObject.Invoke method and get result.

A Python code:

class Door:

def __init__(self, color, height, width):

self.color = color

self.height = height

self.width = width

def getDoorDescription(self, comment):

return comment + ". Color: " + self.color + " Size: " + str(self.height) + "X" + str(self.width) + " mm"

A Fore code:

Var
    pUtils: IPythonUtils;
    pObj: IPythonClassObject;
    Result: Variant;
Begin
    pUtils := 
New PythonUtils.Create;
    pUtils.AddFolderToPythonPath(
"d:\Work\Python\");
    
//Create an object of the Door class
    pObj := New PythonClassObject.Create("sample""Door""Red"2000800);
    
//Get value of the color attribute
    Result := pObj.GetAttr("color");
    Debug.WriteLine(Result);
    
//Change value of the color attribute
    pObj.SetAttr("color""White");
    
//Execute function of the class instance
    Result := pObj.Invoke("getDoorDescription""Connecting door");

After executing the example, an instance of the Python class with the specified attribute values will be created. Next, the color attribute will be obtained and modified. The getDoorDescription function that returns the string result will be executed.

Using Named Parameters

If default values are determined for parameters of Python function, and the function must be executed by setting only specific parameter values, named parameters can be used. To create a named parameter, use the PythonParameter class. Create parameters with required names and values, send them to the Invoke method.

A Python function:

def getMathOperationWithOperands(a = 0, b = 0, c = 0):

if (a != 0) and (b != 0) and (c != 0):

return ((a + b) * c)

elif (a != 0) and (b != 0):

return a+b

elif (a != 0) and (c != 0):

return a-c

elif (b != 0) and (c != 0):

return b*c

else:

return -1

A Fore code:

Var
    pUtils: IPythonUtils;
    pObj1, pObj2: IPythonValueObject;
    pParam1, pParam2: IPythonParameter;
    Result: Variant;
Begin
    pUtils := 
New PythonUtils.Create;
    pUtils.AddFolderToPythonPath(
"d:\Work\Python\");
    
//Create objects with values
    pObj1 := New PythonValueObject.Create(100);
    pObj2 := 
New PythonValueObject.Create(200);
    
//Create named parameters
    pParam1 := New PythonParameter.Create("a", pObj1);
    pParam2 := 
New PythonParameter.Create("c", pObj2);
    
//Execute function
    Result := pUtils.Invoke("sample""getMathOperationWithOperands", pParam1, pParam2);

After executing the example two named parameters with values are created. The getMathOperationWithOperands Python function will be executed with those parameters.

Working with Python Data Types

Simple data types in the Fore language, such as, String, Char, Integer, Double, Decimal, Currency, Boolean, are compatible with data types in the Python language, that, is, str, int, float, bool. Values of these types can be sent to Python functions or obtained after executing Python functions without any additional transformations. It is also possible to work with such Python data types as list and tuple. To work with a list, use the IPythonList interface, to work with a tuple, use the IPythonTuple interface. If the function returns list or tuple, cast result of the Invoke method work to the appropriate interface. To create a new list, use the PythonList class, to create a new tuple, use the PythonTuple class.

A Python function:

def getSizeOfList(l):

return l.__sizeof__()

A Fore code:

Var
    pUtils: IPythonUtils;
    pList: IPythonList;
    pTuple: IPythonTuple;
    Result: Variant;
Begin
    pUtils := 
New PythonUtils.Create;
    pUtils.AddFolderToPythonPath(
"d:\Work\Python\");
    
//Create list and tuple
    pList := New PythonList.Create(0"A", Char.Chr(169));
    pTuple := New PythonTuple.Create(0"A", Char.Chr(169));
    //Get information about list
    Result := pUtils.Invoke("sample""getSizeOfList", pList);
    Debug.WriteLine(
"Number of elements in the list: " + pList.Length.ToString);
    Debug.WriteLine(
"Size of memory used (bites): " + Result);
    
//Get information about tuple
    Result := pUtils.Invoke("sample""getSizeOfList", pTuple);
    Debug.WriteLine(
"Number of elements in the list: " + pTuple.Length.ToString);
    Debug.WriteLine(
"Size of memory used (bites): " + Result);

On executing the example the objects that contain a Python list and tuple are created. Each object will be sent to the getSizeOfList function to get size of the memory it occupies. The number of list and tuple elements, and size of occupied memory are displayed in the development environment console.

Handling Exceptions

All exceptions are handled using the Try…Except…Finally…End Try statement. To handle the errors that may occur on executing a Python function, use the PythonException class.

Var
    pUtils: IPythonUtils;
    Result: Variant;
Begin
    pUtils := 
New PythonUtils.Create;
    pUtils.AddFolderToPythonPath(
"d:\Work\Python\");
    Try
        Result := pUtils.Invoke(
"sample""summXY""a"100);
        Debug.WriteLine(Result);
    
Except On e: PythonException Do
        Debug.WriteLine(e.Message);
    
End Try;

This code executes the summXY function, specified above, with various types parameters. On executing the code, possible exceptional situations are processed using the Try…Except…Finally…End Try operator. If error occurs while execution, text of error will be displayed in the development environment console.

See also:

About the Python Assembly | Python Assembly Hierarchy