Qore python Module
1.0.2
|
The python
module allows for transparent and dynamic bidirectional importined code from Qore to Python and vice-versa. Qore classes can inherit Python classes and extend them, and Python classes can inherit Qore classes and extend them as well; even Qore abstract classes can be inherited by Python classes and made concrete by implementing the requried concrete methods in Python.
This module also implements support in the same shared object for the qoreloader
module for Python so allow native Python code to import Qore APIs; see qoreloader Module for more information.
This module is released under the MIT license (see COPYING.MIT
in the source distribution for more information). The module is tagged as such in the module's header (meaning it can be loaded unconditionally regardless of how the Qore library was initialized).
To use the module in a Qore script, use the %requires
directive as follows:
Helper Qore classes provided by this module:
Class | Description |
PythonProgram | Allows Python code to be embedded and executed in Qore |
To import Python APIs and definitions into a Qore program, the following python-module-specific module command can be used, which also causes the python module to be loaded and initialized if necessary:
Elements can be added to the Python import module path by using the following module command:
The path given is also subjected to environment variable substitutions; the environment variable name must be prefixed with a "$"
char and then can be given either surrounded by "()"
or "{}"
brackets, of if no brackets are used, the environment variable must fit the following pattern: [a-zA-Z0-9_] (alphanumeric + "_"
).
Python code can be parsed immediately using the following module command:
Python classes can be explicitly exported to Qore with the following module command:
Python functions can be explicitly exported to Qore with the following module command:
Qore APIs and definitions can be imported into a Python program by using the following module command:
When Python code inherits Qore classes, the Qore constructor must be explicitly called in the Python __init__()
method as in the following example.
The following module command can be used to create an alias in Python code:
This is often used when importing Qore namespaces to Python to create an alias directly from a child Qore namespace to a Python module or package that is more convenient to access in Python code.
This module implements support for multiple Python interpreters along with multithreading by managing the Python interpreter thread state manually.
Additionally, the Python recursion limit is also set automatically depending on the current thread stack size set in Qore.
This is done to avoid crashes due to stack exhaustion in combination Qore and Python code.
To avoid RecursionError
exceptions when mixing Qore and Python in multithreaded code, make sure the thread stack size is set to an appropriate size in Qore (using set_default_thread_stack_size()
before the Python interpreter is created, for example); the Python recursion limits are then calculated and managed dynamically according to the thread stack size and thread stack usage at the time of context switches to Python.
The Qore python module can also be aliased or symlinked to "qoreloader.so"
("qoreloader.pyd"
on Windows) and placed in the Python module path (PYTHONPATH
), as the Qore binary module also implement code for the qoreloader
Python module in the same shared object, which allows Python programs to dynamically initialize the Qore library from Python programs and then import Qore APIs into Python using an injected qore
package.
The qoreloader
module implements the following functionality:
For example, for Python to import the Qore SqlUtil
module, the following code can be used.
When Qore modules are imported, the lowest namespace created by the module is imported as the new Python module under the Python qore
package.
See the next section about importing the special
module.qore.__root__
qore.__root__
, using any other submodule name other than __root__
after qore
will cause a Qore module to be loaded. If the Qore module cannot be found, an appropriate exception is thrown.The special qore
package has a special module called __root__
which represents the root namespace of the Qore program object.
Importing qore.__root__
module causes all symbols to be imported into the Python program.
Because Qore namespaces are imported as Python modules, any existing Qore namespace can be imported into a Python program using the qore.__root__
module as in the following examples:
qore.__root__
does not cause any external Qore modules to be loaded; it just imports existing Qore namespaces into the Python program. To load a Qore module explicitly, use a Qore module name after qore
.The python
module implements support for using Qore's jni
module to import Java code dynamically into Qore and then into Python using the java
package.
To import Java classes into Python, import the java class by prefixing "java."
to the package path name.
For example, to import the Java java.util.HashMap
class into Python, the following code can be used.
You can also set the classpath for Java imports as in the following example:
When Java packages and classes are imported, the lowest package created by the module is imported as the new Python module under the Python java
package.
The given APIs are first dynamically imported into Qore, and then the Qore APIs are imported dynamically into Python.
This is the easiest way to import Java APIs into Python.
Wildcard imports from Java are not currently directly supported, however you can import the Java package as a Python module and then the classes in the module will be dynamically created when they are referenced. See the following example:
from java.some.package.path import *
are not yet supported, as once the Python module is created, the dynamic attribute lookups in the the global dictionary are not executed at runtime using the wildcard import information, therefore all Java classes to be imported should be either explicitly listed in the import
statement, or the entire package should be imported as above; a "*"
wildcard import will only work if the required Java classes have already been imported into the Qore program container in advance otherwise.The python
module implements support for using Qore's jni
module to import Java code dynamically into Qore and then into Python using a two-step process.
To import Java code first into Qore, use qoreloader.load_java() with the Java dot path to the class name to load, and then import the Qore class into Python using the qore.__root__ module as in the following example:
To set the Java classpath, call the qoreloader.issue_module_cmd() function with the first argument set to "jni"
and the second set to "add-classpath <classpath>"
or "add-relative-classpath <classpath>"
as needed.
module:
the name of the Qore module where the command will be issuedcmd:
the full command to be issuedpath:
the dot path to the Java class to be loaded into Qore, after which it can be imported into Python under Python module "qore.__root__.Jni"
; for example, path = 'javax.jms.Message'
would be then imported into Python with "from qore.__root__.Jni.javax.jms import Message"
."qore.__root__.Jni"
Source Qore Type | Target Python Type |
binary | bytearray |
bool | bool |
date | datetime.datetime (absolute date/time values) or datetime.delta (relative date/time values) |
float | float |
hash | dict |
int | int |
list | list |
list | string |
code (closure or call reference) | callable |
Source Python Type | Target Qore Type |
bool | bool |
int | int or number if greater than 64-bits |
float | float |
bytes | binary |
bytearray | binary |
datetime.datetime | date (absolute date/time values) |
datetime.delta | date (relative date/time values) |
dict | hash |
list | list |
string | list |
tuple | list |
function , method | code |
All other Python types are converted to a Qore object using a dynamically-created class that wraps the Python type or class.
Python exceptions are mapped to Qore exceptions as follows:
err:
the fully-qualified Python exception class name (ex: "builtins.SyntaxError"
, "socket.timeout"
)desc:
the string description, if none, then the exception arguments converted to a string with repr()
arg:
the Python exception object itself converted to a Qore valueQore's deterministic garbage collection approach and reliance on destructors means that Qore objects created by Python must have their lifecycles managed externally.
Python objects wrapping Qore objects hold only weak references to Qore objects.
By default, Qore objects are saved in thread-local data, so the lifecycle of the object is automatically limited to the existence of the thread.
The thread-local hash key name used to save the list of objects created is determined by the value of the "_python_save"
thread-local key, if set. If no such key is set, then "_python_save"
is used instead as the literal key for saving the list of objects.
The lifecycle of Qore objects can be managed explicitly by using the PythonProgram::setSaveObjectCallback() method to set a callback that is called every time a Qore object is created using the Python API.
This callback must take a single object argument as in the following example: