Template project with various python code examples to be used with the InterSystems IRIS Community Edition docker container.
Featuring :
- Notebooks
- Embedded Python Kernel
- ObjectScript Kernel
- Vanilla Python Kernel
- Embedded Python
- Code example
- Flask demo
- IRIS Python Native APIs
- Code example
Architecture of the container:
- 1. iris-python-template
- 2. Table of Contents
- 3. Installation
- 4. How to start coding
- 5. What's inside the repository
Make sure you have git and Docker Desktop installed.
The git repo is dockerised so you can clone/pull it into any local directory:
git clone https://github.com/grongierisc/iris-python-template.git
To verify the installation, open a terminal in iris-python-template
directory this creates, and start the container by running:
docker-compose up -d
Open http://localhost:8888/tree to work in Jupyter Notebooks using a web browser.
Stop the container by running:
docker-compose down
This repository is ready for VS Code.
Open the locally-cloned iris-python-template
folder in VS Code.
If prompted (bottom right corner), install the recommended extensions.
When prompted, reopen the folder inside the container so you will be able to use the python components within it. The first time you do this it may take several minutes while the container is readied.
Open /src/ObjectScript/Embedded/Python.cls
make changes and save. The class will be compiled in IRIS in the container.
By opening the folder remote you enable VS Code and any terminals you open within it to use the python components within the container. Configure these to use /usr/irissys/bin/irispython
Open this URL from a browser: http://localhost:8888/tree
Or open it via the quickpick which appears when you click on the IRIS connection panel in the status bar:
Then you have access to three different notebooks, each using a different kernel.
- Embedded Python kernel
- ObjectScript kernel
- Vanilla python3 kernel
VS Code offers native support for notebooks, including Jupyter notebooks.
Open any of the .ipynb
notebook files in the src\Notebooks
folder in the Explorer panel.
A dockerfile which install some python dependencies (pip, venv) and sudo into the container for convenience. Then it create the dev directory and copies into it this git repository.
It starts IRIS and imports the Titanic passenger list csv file, then it activates %Service_CallIn for Python Shell. Use the related docker-compose.yml to easily set up additional parameters like port number and where you map keys and host folders.
This dockerfile ends with the installation of requirements for python modules.
The last part is about installing jupyter notebook and its kernels.
Use .env/ file to adjust the dockerfile being used in docker-compose.
File enabling VS Code to open the workspace remotely inside the container.
This is very useful to work with IRIS Embedded Python.
Settings file to let you immediately code in VS Code with the VS Code ObjectScript plugin
Config file if you want to debug with VS Code ObjectScript
Read about all the files in this article
Recommendation file to add extensions if you want to work with VS Code.
This folder is devied in two parts, one for ObjectScript example and one for python code.
Different piece of code that shows how to use python in IRIS.
Some comments are in French to let you improve your French skills too.
/// Embedded python example
Class ObjectScript.Embbeded.Python Extends %SwizzleObject
{
/// HelloWorld with a parameter
ClassMethod HelloWorld(name As %String = "toto") As %Boolean [ Language = python ]
{
print("Hello",name)
return True
}
/// Description
Method compare(modèle, chaine) As %Status [ Language = python ]
{
import re
# compare la chaîne [chaîne] au modèle [modèle]
# affichage résultats
print(f"\nRésultats({chaine},{modèle})")
match = re.match(modèle, chaine)
if match:
print(match.groups())
else:
print(f"La chaîne [{chaine}] ne correspond pas au modèle [{modèle}]")
}
/// Description
Method compareObjectScript(modèle, chaine) As %Status
{
w !,"Résultats("_chaine_","_modèle_")",!
set matcher=##class(%Regex.Matcher).%New(modèle)
set matcher.Text=chaine
if matcher.Locate() {
write matcher.GroupGet(1)
}
else {
w "La chaîne ["_chaine_"] ne correspond pas au modèle ["_modèle_"]"
}
}
/// Description
Method DemoPythonToPython() As %Status [ Language = python ]
{
# expression régulières en python
# récupérer les différents champs d'une chaîne
# le modèle : une suite de chiffres entourée de caractères quelconques
# on ne veut récupérer que la suite de chiffres
modèle = r"^.*?(\d+).*?$"
# on confronte la chaîne au modèle
self.compare(modèle, "xyz1234abcd")
self.compare(modèle, "12 34")
self.compare(modèle, "abcd")
}
Method DemoPythonToObjectScript() As %Status [ Language = python ]
{
# expression régulières en python
# récupérer les différents champs d'une chaîne
# le modèle : une suite de chiffres entourée de caractères quelconques
# on ne veut récupérer que la suite de chiffres
modèle = r"^.*?(\d+).*?$"
# on confronte la chaîne au modèle
self.compareObjectScript(modèle, "xyz1234abcd")
self.compareObjectScript(modèle, "12 34")
self.compareObjectScript(modèle, "abcd")
}
/// Description
Method DemoObjectScriptToPython() As %Status
{
// le modèle - une date au format jj/mm/aa
set modèle = "^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$"
do ..compare(modèle, "10/05/97")
do ..compare(modèle, " 04/04/01 ")
do ..compare(modèle, "5/1/01")
}
}
- HelloWorld
- Simple function to say Hello in python
- It uses the OjectScript wrapper with the tag [ Language = python ]
- compare
- An python function that compare a string with a regx, if their is a match then print it, if not print that no match has been found
- compareObjectScript
- Same function as the python one but in ObjectScript
- DemoPythonToPython
- Show how to use a python function with python code wrapped in ObjectScript
set demo = ##class(ObjectScript.Embbeded.Python).%New()
zw demo.DemoPythonToPython()
- DemoPythonToObjectScript
- An python function who show how to call an ObjecScript function
- DemoObjectScriptToPython
- An ObjectScript function who show how to call an python function
An ObjectScript class who show how to call an external phyton code with the gateway functionnality.
In this example python code is not executed in the same process of IRIS.
/// Description
Class Gateway.Python
{
/// Demo of a python gateway to execute python code outside of an iris process.
ClassMethod Demo() As %Status
{
Set sc = $$$OK
set pyGate = $system.external.getPythonGateway()
d pyGate.addToPath("/irisdev/app/src/Python/gateway/Address.py")
set objectBase = ##class(%Net.Remote.Object).%New(pyGate,"Address")
set street = objectBase.street
zw street
Return sc
}
}
Different piece of python code that shows how to use IRIS Embedded Python.
Some comments are in French to let you impove your French skills too.
import iris
person = iris.cls('Titanic.Table.Passenger')._OpenId(1)
print(person.__dict__)
First import iris module that enable embedded python capabilities.
Open an persistent class with cls function from iris module.
Note that all %
function are replaced with _
.
To run this example you have to use iris python shell :
/usr/irissys/bin/irispython /opt/irisapp/src/Python/embedded/demo.py
Show how to use native API in python code.
import irisnative
# create database connection and IRIS instance
connection = irisnative.createConnection("localhost", 1972, "USER", "superuser", "SYS", sharedmemory = False)
myIris = irisnative.createIris(connection)
# classMethod
passenger = myIris.classMethodObject("Titanic.Table.Passenger","%OpenId",1)
print(passenger.get("name"))
# global
myIris.set("hello","myGlobal")
print(myIris.get("myGlobal"))
To import irisnative, you have to install the native api wheels in your python env.
pip3 install /usr/irissys/dev/python/intersystems_irispython-3.2.0-py3-none-any.whl
Then you can run this python code
/usr/bin/python3 /opt/irisapp/src/Python/native/demo.py
Note that in this case a connection is made to iris database, this mean, this code is executed in a different thread than the IRIS one.
A full demo of the combination between IRIS Embedded Python and the micro framework flask. You can test this end point :
GET http://localhost:4040/api/passengers?currPage=1&pageSize=1
In order to use Embedded Python, we use irispython
as a python interpreter, and do:
import iris
Right at the beginning of the file.
We will then be able to run methods such as:
As you can see, in order to GET a passenger with an ID, we just execute a query and use its result set.
We can also directly use the IRIS objects:
Here, we use an SQL query to get all the IDs in the table, and we then retreive each passenger from the table with the %OpenId()
method from the Titanic.Table.Passenger
class (note that since %
is an illegal character in python, we use _
instead).
Thanks to Flask, we implement all of our routes and methods that way.
To launch the server, we use gunicorn
with irispython
.
In the docker-compose file, we add the following line:
iris:
command: -a "sh /opt/irisapp/server_start.sh"
That will launch, after the container is started (thanks to the -a
flag), the following script:
#!/bin/bash
cd ${SRC_PATH}/src/Python/flask
${PYTHON_PATH} -m gunicorn --bind "0.0.0.0:8080" wsgi:app &
exit 1
With the environment variables defined in the Dockerfile as follows:
ENV PYTHON_PATH=/usr/irissys/bin/irispython
ENV SRC_PATH=/opt/irisapp/
Three notebooks with three different kernels :
- One Python3 kernel to run native APIs
- One Embedded Python kernel
- One ObjectScript kernel
Notebooks can be access here http://localhost:8888/tree or directly from VS Code's Explorer view.
This notebook uses an IRIS Embedded Python kernel.
It shows example to open and save persistent classes and how to run SQL queries.
This notebook uses a vanilla python kernel.
It shows example run iris native apis.
This notebook uses an ObjectScript kernel.
It shows example to run ObjectScript code and how to use Embedded Pythoon in ObjectScript.