Artículo
Alberto Fuentes · Oct 14, 2022 Lectura de 11 min

Ejemplos en Python de InterSystems IRIS 2021.2+ (Embebido, APIs nativas y Notebooks)

Iris-python-template

Proyecto de plantilla con varios códigos Python para ser utilizados con InterSystems IRIS Community Edition con contenedor.

Contenido:

  • Bloc de notas
    • Kernel de Python Embebido
    • Kernel de ObjectScript
    • Kernel de Vanilla Python
  • Python Embebido
    • Ejemplo de código
    • Demostración de Flask
  • API nativas de Python de IRIS
    • Ejemplo de código

Diagrama

2. Índice

3. Instalación

3.1. Docker

El repositorio está dockerizado para que puedas clonar el repositorio a cualquier directorio local

git clone https://github.com/grongierisc/iris-python-template.git

Abre el terminal en este directorio y ejecuta:

docker-compose up -d

y abre después http://localhost:8888/tree para Notebooks

O bien, abre la carpeta clonada en VSCode, inicia docker-compose y abre la URL mediante el menú de VSCode:
VsCodeNotebooks

4. Cómo empezar a programar

4.1. Requisitos previos

Asegúrate de tener instalado git y Docker desktop.

Este repositorio está listo para codificarse en VSCode con el plugin de ObjectScript. Instala VSCode,Docker yel plugin de ObjectScripty abre la carpeta en VSCode.

4.1.1. Empezar a programar en ObjectScript

Abre la clase /src/ObjectScript/Embedded/Python.cls e intenta hacer cambios - se compilará en el contenedor Docker IRIS que está funcionando.

4.1.2. Empezar a programar con Python Embebido

La forma más fácil es ejecutar VsCode en el contenedor.

Para adjuntar a un contenedor Docker, selecciona Remote-Containers: Attach to Running Container... en la plantilla de comandos (kbstyle(F1)) o utiliza el Remote Explorer en la barra de actividades y desde la vista Containers, selecciona la acción en línea Attach to Container en el contenedor al que quieras conectarte.

Captura de pantalla del Explorador de contenedores

A continuación, configura tu intérprete de python en /usr/irissys/bin/irispython

PythonInterpreter

4.1.3. Empezar a programar con Notebooks

Abre esta URL: http://localhost:8888/tree

Tienes acceso a tres notebooks diferentes con tres kernels diferentes.

  • Kernel de Python Embebido
  • Kernel de ObjectScript
  • Kernel de Vanilla Python3

Bloc de notas

5. Qué hay dentro del repositorio

5.1. Dockerfile

Un dockerfile que instala algunas dependencias de Python (pip, venv) y Sudo en el contenedor por conveniencia. Después crea el directorio dev y copia en él este repositorio git.

Inicia IRIS e importa los archivos Titanics csv, después activa %Service_CallIn para Python Shell. Utiliza el docker-compose.yml relacionado para configurar fácilmente parámetros adicionales como el número de puerto y dónde asignar claves y carpetas del host.

Este dockerfile termina con la instalación de los requisitos para los módulos de Python.

La última parte es sobre la instalación de Jupyter Notebook y sus kernels.

Utiliza el archivo .env/ para ajustar el dockerfile que se utiliza en docker-compose.

5.2. .vscode/settings.json

Archivo de configuración para poder codificar inmediatamente en VSCode con el plugin VSCode ObjectScript

5.3. .vscode/launch.json

Archivo de configuración si quieres depurar con VSCode ObjectScript

Lee sobre todos los archivos en este artículo

5.4. .vscode/extensions.json

Archivo de recomendación para añadir extensiones si quieres ejecutar VSCode en el contenedor.

Más información aquí

Arquitectura

Esto es muy útil para trabajar con Python Embebido.

5.5. src folder

Esta carpeta está concebida en dos partes, una para el ejemplo de ObjectScript y otra para el código de Python.

5.5.1. src/ObjectScript

Un código diferente que muestra cómo utilizar Python en IRIS.

5.5.1.1. src/ObjectScript/Embedded/Python.cls

Todos los comentarios están en francés para que también puedas mejorar tu nivel de francés.

/// 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 DemoPyhtonToPython() 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 DemoPyhtonToObjectScript() 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
    • Función sencilla para decir "Hola" en Python
    • Utiliza la envoltura OjectScript con la etiqueta [ Language = python ]
  • compare
    • Una función de python que compara una cadena con un regx, si hay una coincidencia entonces la imprime, si no la imprime es que no se encontró ninguna coincidencia
  • compareObjectScript
    • La misma función que la de Python pero en ObjectScript
  • DemoPyhtonToPython
    • Muestra cómo utilizar una función de Python con código de Python envuelto en ObjectScript
set demo = ##class(ObjectScript.Embbeded.Python).%New()

zw demo.DemoPyhtonToPython()
  • DemoPyhtonToObjectScript
    • Una función de Python que muestra cómo llamar a una función de ObjecScript
  • DemoObjectScriptToPython
    • Una función de ObjectScript que muestra cómo llamar a una función de Python

5.5.1.2. src/ObjectScript/Gateway/Python.cls

Una clase de ObjectScript que muestra cómo llamar a un código de Phyton externo con la funcionalidad gateway.

En este ejemplo el código de Python es no ejecutado en el mismo proceso de 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
}

}

5.5.2. src/Python

Una pieza diferente del código Python que muestra cómo usar Python Embebido en IRIS.

5.5.2.1. src/Python/embedded/demo.cls

Todos los comentarios están en francés para que también puedas mejorar tu nivel de francés.

import iris

person = iris.cls('Titanic.Table.Passenger')._OpenId(1)

print(person.__dict__)

Primero importa el módulo de IRIS que activa las funciones de Python Embebido. Abre una clase persistente con la función cls del módulo de IRIS. Ten en cuenta que todas las funciones % se sustituyen por _.

Para ejecutar este ejemplo hay que utilizar IRIS Python Shell:

/usr/irissys/bin/irispython /opt/irisapp/src/Python/embedded/demo.py

5.5.2.2. src/Python/native/demo.cls

Muestra cómo utilizar la API nativa en el código de Python.

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"))

Para importar IRISNATIVE, debes instalar las ruedas de las API nativas en tu entorno de Python.

pip3 install /usr/irissys/dev/python/intersystems_irispython-3.2.0-py3-none-any.whl

Entonces puedes ejecutar este código de Python

/usr/bin/python3 /opt/irisapp/src/Python/native/demo.py

Ten en cuenta que en este caso se realiza una conexión a la base de datos de IRIS, esto significa que este código se ejecuta en un subproceso diferente al de IRIS.

5.5.2.3. src/Python/flask

Una demo completa de la combianción entre Python Embebido y el micro framework Flask. Puedes probar este endpoint:

GET http://localhost:4040/api/passengers?currPage=1&pageSize=1
5.5.2.3.1. ¿Cómo funciona?

Para utilizar Python Embebido, usamos irispython como interepretador de Python, y hacemos:

import iris

Justo al principio del archivo.

Entonces podremos ejecutar métodos como:

flaskExample

Como puedes ver, para OBTENER un pasajero con un ID, simplemente ejecutamos una consulta y utilizamos su conjunto de resultados.

También podemos utilizar directamente los objetos de IRIS:

flaskObjectExample

Aquí, utilizamos una consulta SQL para obtener todos los IDs de la tabla, y después recuperamos cada pasajero de la tabla con el método %OpenId() de la clase Titanic.Table.Passenger (ten en cuenta que como % es un carácter ilegal en Python, utilizamos _ como alternativa).

Gracias a Flask, implementamos todas nuestras rutas y métodos de esa manera.

5.5.2.3.2. Lanzamiento del servidor flask

Para lanzar el servidor, usamos gunicornio con irispython.

En el archivo docker-compose, añadimos la siguiente línea:

iris:
  command: -a "sh /opt/irisapp/server_start.sh"

Eso lanzará, después de que se inicie el contenedor (gracias al indicador -a), el siguiente script:

#!/bin/bash

cd ${SRC_PATH}/src/Python/flask

${PYTHON_PATH} -m gunicorn --bind "0.0.0.0:8080" wsgi:app &

exit 1

Con las variables de entorno definidas en el Dockerfile como sigue:

ENV PYTHON_PATH=/usr/irissys/bin/irispython
ENV SRC_PATH=/opt/irisapp/

5.5.3. src/Notebooks

Tres notebooks con tres kernels diferentes:

  • Un kernel de Python3 para ejecutar las API nativas
  • Un kernel de Python Embebido
  • Un kernel de ObjectScript

Se puede acceder a los notebooks aquí: http://localhost:8888/tree

Bloc de notas

5.5.3.1. src/Notebooks/HelloWorldEmbedded.ipynb

Este notebook utiliza el kernel de Python Embebido.

Muestra un ejemplo para abrir y guardar clases persistentes y cómo ejecutar consultas en SQL.

5.5.3.2. src/Notebooks/IrisNative.ipynb

Este notebook utiliza el kernel de Vanila python.

Muestra ejemplo para ejecutar API nativas de IRIS.

5.5.3.3. src/Notebooks/ObjectScript.ipynb

Este notebook utiliza el kernel de ObjectScript.

Muestra un ejemplo para ejecutar el código ObjectSCript y cómo utilizar Python Embebido en ObjectScript.

2
1 52
Debate (0)2
Inicie sesión o regístrese para continuar