Qorus Integration Engine® Enterprise Edition 6.0.27_prod
|
Back to the Developer's Guide Table of Contents
Qorus supports native Python development where code attributes of objects can be defined with code in Python in addition to Java and Qore.
Python integration with Qore is implemented using the python module, which provides tight integration with both languages, including bi-directional dynamic and transparent imports of code and data between Qore and Java and Python as well.
All Qorus APIs are available in Python code in Qorus, however some APIs are automatically imported into Python programs. The main Qorus Python APIs imported into Python program containers as given in the following table.
Python Module Names for Qorus APIs
Type | Python Module | Description |
module | job | The Qorus job module as imported from the main Qorus Qore-language job namespace |
module | OMQ | The main OMQ namespace for Qorus |
module | svc | The Qorus service module as imported from the main Qorus Qore-language service namespace |
module | wf | The Qorus workflow module as imported from the main Qorus Qore-language workflow namespace |
Python Interface API Class Names
Type | Python Class | Description |
class | jobapi | The Python job API class based on the Qore API |
class | svcapi | The Python service API class based on the Qore API |
class | UserApi | The main Python user API class based on the Qore API |
class | wfapi | The Python workflow API class based on the Qore API |
The Python module path can be specified using the module_path
tag in a class object; see Python Module Handling in Qorus for more information and examples.
remote
flag in your interface is True
; see:
for more informationGenerally, the Python module path is set with the tag module_path
when defining Python code in Qorus. Furthermore, the recommended storage location for Python modules is in $OMQ_DIR/user/python
.
The module_path
tag accepts environment variables, and each element in the module path should be separated by a colon (":"
); see the following examples for more information.
In class definitions or any other object with Python code, the Python module_path is set with the YAML metadata tag module_path
as in the following example:
module_path: $OMQ_DIR/user/my-project/python:$OMQ_DIR/user/my-other-project/python
The following directories are automatically added to the Python module path in Qorus:
$OMQ_DIR/user/python/site-packages
$OMQ_DIR/user/python/lib/python<ver>/site-packages
In the last path above, <ver>
is the Python major and minor version; ex: $OMQ_DIR/user/python/lib/python3.8/site-packages
If a release should also package one or more Python modules, the following options to make-release will be needed:
-a=
ARG: this provides the source Python module directory that you want in the release-b=
ARG: this provides the target directory name the files packaged with -a
to be installed under $OMQ_DIR
on the target server; the default location without this option is $OMQ_DIR/user/python/lib/python
<version>/site-packages
where <version> is the major and minor version of Python used (ex: 3.8
)Some Python modules do not support multiple interpreters in the same process; Python code requiring these modules should always run in a separate process (see Workflow Remote Parameter, Service Remote Flag, and Job Remote Flag).
The Python error looks as follows:
builtins.ImportError: Interpreter change detected - this module can only be loaded into one interpreter per process.
Any Qore module can be imported into Python code using the special qore
package provided by the qoreloader module, which is used to dynamically load Qore modules and make them available to the Python import system on demand.
An equivalent Python module is created based on the main namespace detected for the loaded Qore module.
Aside from the Qore modules and classses listed in the above section, any Qore code available in an interface or imported from a Qore module outside the main namespace can be automatically imported and accessed in Python code using the special qore.__root__
module.
The qore.__root__
module provides access to the root Qore namespace and therefore all accessible declarations in Qore.
For example, if a Qore class declared outside of any namespace (therefore finding itself in the root namespace) named MyClass
is imported in a Python interface, it can be accessed as follows:
The following is an example from a Python test:
The python module implements support for multiple Python interpreters in Qorus programs along with multithreading by managing the Python interpreter thread state manually.
Additionally, the Python recursion limit is also set automatically as a function of the current thread stack size; the default stack size for all Qorus programs can be set with the qorus.stack-size option, and this option can furthermore be overridden in each interface by setting a value for the option on the interface directly.
Stack size and Python recursion limits are managed to avoid crashes due to stack exhaustion in Qore and Python code.
Note that the default stack size for Qorus is 8MB; since stack memory is allocated from overcommitted memory and starts small and is allocated real memory only on demand, large stack sizes do not have a affect on the process memory size as long as the program does not use the extra stack space. For programs that require more than 8MB of stack, you can set higher stack sizes by setting the appropriate value of the qorus.stack-size option on each interface directly while also setting the remote
flag to True
on the interface, ensuring that it will be run in a dedicated process. That way the higher stack size will be enforced only for the program that needs it.
remote
flag is False
), any locally-set qorus.stack-size option value is ignored; in qorus-core, only the global qorus.stack-size option is used.Qorus workflows can be defined in Python by implementing a step class by subclassing one of the following step classes for the step:
Qorus services can be defined in Python by subclassing the svc.QorusService class as in the following example:
Qorus jobs can be defined in Python by implementing a job class and subclassing the job.QorusJob class as in the following example.
Python is not subject to sandboxing controls like Qore code, so it's easier to do dangerous things with Python.
All normal Python programming best practices should be followed when programming in Python; make sure all resources are freed in finally
blocks and so forth; Qorus can only manage Qore resources, the Python runtime manages all Python resources normally.
Do not do any of the following:
sys.exit()
, _exit()
, os._exit()
and similar)Qore objects imported into Python are subject to special reference handling. Strong references to the Qore objects are always managed in Qorus, which means that when creating or acquiring a Qore object in Qorus with Python, the object will normally go out of scope after control returns to Qorus, meaning that the Qore destructor is then run, so that Qore's deterministic garbage collector can also be used in Python code.
For example, locks are released when wf.DynamicDataHelper objects are collected after created from Python step code. The same applies to wf.TempDataHelper and wf.SensitiveDataHelper objects.
Qorus's Qore-language client API can be used as in the following example:
To use Qorus (and generally any Qore or Java) APIs in Python, the qoreloader.so
module is required. This module can be found in $OMQ_DIR/python/qoreloader
.so
The following classes can help to write tests written in Python: