Applied Informatics Open Service Platform

OSP Python Integration User Guide

Contents

Introduction

OSP Python provides a service that allows to execute Python code from within bundles. It also exposes POCO's logging framework as a Python module named logger.

Installation

Linux/Mac OS X

The Python distributions that come with Linux distributions and Mac OS X should be fine, so no additional setup is necessary.

Windows

Download

Go to http://www.python.org and download the source-release of Python 2. Latest stable version during the writing of this document is 2.7.2.

Using the Python binary package is not recommended because it only comes with the release build of the python libs which links against msvcrt71. When doing a debug build Python will automatically try to link to its debug build which forces you to build Python yourself. Even if you only need the release build, it is recommended to build your own binary package of Python.

Build

Decompress the Python archive. If you are using a Visual Studio version greater 2003, go to the PCBuild8 folder, else to the PCbuild folder and open its solution file. Build once for Debug and once for Release. Some of the projects will fail to build, but as long as the Python DLL builds we are fine.

The resulting binaries will be in the folder PCbuild[8]/Win32Debug and PCbuild[8]/Win32Release. The include files are stored in the folder Include. Add the Include and Lib folders to your Visual Studio environment (See Tools->Options->Projects and Solutions->VC++ Directories). Copy the python dlls to your search path, copy your py_config.h to the Include directory.

PythonService

The PythonService is available under the name com.appinf.osp.python.callservice. Get the service from the ServcieRegistry and cast it to Poco::OSP::Python::PythonService. The PythonService offers the following groups of methods:

  • exec
  • execute
  • executeStatement

executeStatement

This is the simplest function. It allows to execute a single line Python statement where one is not interested in the return value and where no input parameter formatting is needed. A simple usage example is the importing of modules:

_pService->executeStatement("import sys");

exec

The exec functions are used when one is interested in the return value. They always take a module (if none is specified the mainModule is used), the function to be executed, and up to 6 parameters. For example, if we have defined a test.py file which contains a method named calc which takes three parameters as input and returns one parameter, we will call this function as follows:

int result = _pService->exec<int>("test", "calc", 12, 34, 23.4);

As data types all primitive C++ types are supported plus std::vector<>, Poco::Any and Poco::DynamicAny. If you don't want a return type or you need more than 6 input parameters you must use execute().

execute

Execute is similar to exec with the following differences:

  • input parameters are always passed as a vector of Any
  • it does support return parameter types as templates
  • it supports void as return parameter

Example:

std::vector<Poco::Any> args;
args.push_back(12);  
args.push_back(34);
args.push_back(23.4);
int res = _pService->execute<int>("test", "calc", args);
// example for a function without params and without return value
execute("myModule", "doNothing");

Extension Points

The Python package defines two extension points:

  • com.appinf.osp.python.import
  • com.appinf.osp.python.startup

Import Extension Point

The import extension point adds a a search path to Python's sys.path. It supports one optional path attribute. If the path attribute is not defined, the whole bundle is added to the search path, otherwise only the given subdirectory of the bundle. You can't add single files, path must always be a directory.

Example for extensions.xml which imports everything of the owner bundle:

<extensions>
    <extension point="com.appinf.osp.python.import"/>
</extensions>         

Example for extensions.xml which imports the directory 'python' of the owner bundle:

<extensions>
    <extension point="com.appinf.osp.python.import" path="python"/>
</extensions>

Startup Extension point

The startup extension point allows to specify one single Python function (parameter-less) that should be executed upon startup of the bundle. It has two mandatory attributes: module and function. module defines from which Python file/module the function should be called, function is the name of the function without any parameters or brackets.

Example for extensions.xml which starts fib.initialize():

<extensions>
    <extension point="com.appinf.osp.python.startup" module="hello" function="startup"/>
</extensions>

Logging

The Python bundle provides a logger module which allows you to write directly to POCO's loggers from within Python code. Simply import logger and call one of the following functions:

import logger
logger.fatal(loggerName, message)
logger.critical(loggerName, message)
logger.error(loggerName, message)
logger.warning(loggerName, message)
logger.notice(loggerName, msg)
logger.information(loggerName, message)
logger.debug(loggerName, message)
logger.trace(loggerName, message)

Both the loggerName and the message parameter must be strings.

Writing your own Modules

When integrating your own C/C++ code into Python (assuming you use SWIG) stick to the following guidelines:

  • Windows only: when you write a module named name, the DLL name must be _name.pyd for the release build, and _name_d.pyd for the debug build
  • on Unix platforms you use the standard .so suffix (this also applies to Mac OS X, where .so has to be used instead of .dylib).
  • simply include the created pyd files in the code part of the bundlespec. The OSP codeCache directory is automatically added to the Python search path allowing you to load the pyd files from there.
  • always include all types (ie std_string.i for string data type) in the Python interface file.