Pesquisar

文章
· 九月 12, 2024 阅读大约需 7 分钟

Embedded python in InterSystems IRIS

Hello Community,

In this article, I will outline and illustrate the process of implementing ObjectScript within embedded Python. This discussion will also reference other articles related to embedded Python, as well as address questions that have been beneficial to my learning journey.

As you may know, the integration of Python features within IRIS has been possible for quite some time. This article will focus on how to seamlessly incorporate ObjectScript with embedded Python.

Essentially, embedded Python serves as an extension that allows for independent writing and execution. It enables the seamless integration of Python code with ObjectScript and vice versa, allowing both to run within the same context. This functionality significantly enhances the capabilities of your implementation.

To begin, you must specify the language for your Python code within the class definition by using the "language" keyword [language = "python"]. Once this is done, you are prepared to write your Python code.

import iris - The iris package is a vital Python library that facilitates communication with InterSystems' native API classes, routines, globals, and SQL. This package is readily available by default. Anyway It is necessary to import this package at the beginning of your python code if you're going to interact with IRIS.

Few important notes before writing

  • You can use python special variable __name__ to refer the classname inside the class definition.
  • Use _ for %Methods ex: %New  == _New , %OpenId == _OpenId

Let's begin

Class members implementation in Embedded python

1.  Objects and Properties

This section is essential as it will cover the process of initializing a new object, altering the values of existing objects, and configuring properties in both static and dynamic contexts. Create your own class definition and use the simple literal properties

1.1 initialize new Object / Modify existing object

Use _New for initiate new object and _OpenId(id) for edit the existing object

ClassMethod SaveIRISClsObject() [ Language = python ]
{
 #this method calls the %OnNew callback method and get the object
 import iris
 try:
     iris_obj =  iris.cls(__name__)._New()
     if not iris.cls(__name__).IsObj(iris_obj):
      #IsObj is the objectscript wrapper method : which contains $Isobject()
         raise ReferenceError('Object Initlize Error')
 except ReferenceError as e:
     print(e)
     return
 #set the object properties and save the values
 iris_obj.Name = 'Ashok'
 iris_obj.Phone = 9639639635
 status = iris_obj._Save()
 print(status)
 return status
}

1.2 Accessing properties

Prior to commencing the property section, it is important to note that the IRIS data type differs from Python data types, and therefore, IRIS collection data types cannot be utilized directly within Python. To address this, InterSystems has offered a comprehensive solution for converting IRIS data types into Python-compatible formats such as lists, sets, and tuples. This can be achieved by importing the "builtins" module within the IRIS code base, utilizing the class methods ##class(%SYS.Python).Builtins() or by setting builtins = ##class(%SYS.Python).Import("builtins"). I'll cover this in upcoming sections.

So, I use this method to convert the $LB properties into python list for accessing the properties at runtime in python

LEARNING>Set pyList = ##class(%SYS.Python).ToList($LB("Name","Phone","City"))
 
LEARNING>zw pyList
pyList=5@%SYS.Python  ; ['Name', 'Phone', 'City']  ; <OREF>
ClassMethod GetProperties() [Language = objectscript]
{
    set pyList = ##class(%SYS.Python).ToList($LB("Name","Phone","City"))
    do ..pyGetPropertiesAtRunTime(pyList)
}
ClassMethod pyGetPropertiesAtRunTime(properties) [ Language = python ]
{
    import iris
    iris_obj = iris.cls(__name__)._OpenId(1)
    for prop in properties:
        print(getattr(iris_obj,prop))
}

 

1.3 Set properties at runtime.

I utilize this python dictionary to designate my property as a key and, with the corresponding property values serving as the values within that dictionary. You may refer to the code provided below and the community post regarding this property set.

ClassMethod SetProperties()
{
	Set pyDict = ##class(%SYS.Python).Builtins().dict()
	do pyDict.setdefault("Name1", "Ashok kumar")
	do pyDict.setdefault("Phone", "9639639635")
	do pyDict.setdefault("City", "Zanesville")
	Set st = ..pySetPropertiesAtRunTime(pyDict)
}

ClassMethod pySetPropertiesAtRunTime(properties As %SYS.Python) [ Language = python ]
{
	import iris
	iris_obj = iris.cls(__name__)._New()
	for prop in properties:
		setattr(iris_obj, prop,properties[prop])
	
	status = iris_obj._Save()
	return status
}

1.4 Object share context

As previously stated, both Python and ObjectScript operate within the same memory context and share objects. This implies that you can create or open an object in the InCache class and subsequently set or retrieve it in the Python class.

ClassMethod ClassObjectAccess() [Language = objectscript]
{
	Set obj = ..%OpenId(1)
	Write obj.PropAccess(),! ; prints "Ashok kumar"
	Do obj.DefineProperty("test")
	Write obj.PropAccess() ; prints "test"
}

Method PropAccess() [ Language = python ]
{
	
return self.Name
}

Method DefineProperty(name) [ Language = python ]
{
	
self.Name = name
}

2.  Parameters

Get the parameter arbitrary key value pair by using the _GetParameter. Refer the useful community post 

ClassMethod GetParam(parameter = "MYPARAM") [ Language = python ]
{
	import iris
	value = iris.cls(__name__)._GetParameter(parameter)
	print(value)
}

3. Class Method and Methods

3.1 Class Method

The invocation of class methods and functions is highly beneficial for executing the object script code.

Invoke the class method as a static call ex: Do ..Test() 

ClassMethod InvokeStaticClassMethods(clsName = "MyLearn.EmbeddedPython") [ Language = python ]
{
	import iris
	print(iris.cls(clsName).Test())
	# print(iris.cls(__name__).Test()) 
}


Invoke the Class method at runtime Set method="Test" Do $ClassMethod(class, method, args...)

ClassMethod InvokeClassMethodsRunTime(classMethod As %String = "Test") [ Language = python ]
{
 import iris
 clsMethodRef = getattr(iris.cls(__name__), classMethod) # will return the reference of the method
 print(clsMethodRef()) 
}

3.2  Methods

Invoke the instance methods are same as "object script" format. In the below code I've initiate the object first and call the instance method with parameters.

ClassMethod InvokeInstanceMethodWithActualParameters() [ Language = python ]
{
	import iris
	obj = iris.cls(__name__)._New()
	print(obj.TestMethod(1,2,4))
}

3.3  Pass arguments by value and reference b/w python and objectscript

Basically passing the arguments are inevitable between the functions and the same will remain between ObjectScript and python

3.4  Pass by value - It's as usual pass by value

ClassMethod passbyvalfromCOStoPY()
{
    Set name = "test", dob= "12/2/2002", city="chennai"
    Do ..pypassbyvalfromCOStoPY(name, dob, city)
}

ClassMethod pypassbyvalfromCOStoPY(name As %String, dob As %String, city As %String) [ Language = python ]
{
   print(name,'  ',dob,'  ',city)
}

/// pass by value from  python to object script
ClassMethod pypassbyvalfromPY2COS() [ Language = python ]
{
	import iris
	name = 'test'
	dob='12/2/2002'
	city='chennai'
	iris.cls(__name__).passbyvalfromPY2COS(name, dob, city)
}

ClassMethod passbyvalfromPY2COS(name As %String, dob As %String, city As %String)
{
    zwrite name,dob,city
}

3.5 Pass by reference- Unlike the pass by value. Since Python does not support call by reference natively, so, you need to use the iris.ref()  in python code to make it the variable as a reference. refer the reference. To the best of my knowledge, there are no effects on the object script side regarding pass-by-reference variables, even when these variables are modified in Python. Consequently, Python variables will be affected by this pass-by-reference mechanism when the methods of the object script are invoked

ClassMethod pypassbyReffromPY2COS() [ Language = python ]
{
	import iris
	name='python'
	dob=iris.ref('01/01/1991')
	city = iris.ref('chennai')
	print('before COS ',name,'  ',dob.value,'  ',city.value)
	#pass by reference of dob, city
	iris.cls('MyLearn.EmbeddedPythonUtils').passbyReffromPY2COS(name, dob, city)	
	print('after COS ',name,'  ',dob.value,'  ',city.value)
}

ClassMethod passbyReffromPY2COS(name, ByRef dob, ByRef city)
{
  Set name="object script", dob="12/12/2012", city="miami"
}

// output 
LEARNING>do ##class(MyLearn.EmbeddedPythonUtils).pypassbyReffromPY2COS()
before COS  python    01/01/1991    chennai
after COS  python    12/12/2012    miami
 


3.5 **kwargs- There is an additional support for passing the python keyword arguments (**kwargs) from object script. Since InterSystems IRIS does not have the concept of keyword arguments, you have to create a  %DynamicObject to hold the keyword/value pairs and pass the values as syntax Args...

I have created the dynamicObject  "name""ashok""city""chennai"}and set the required key-value pairs in it and eventually pass to the python code.

ClassMethod KWArgs()
{
    set kwargs={ "name": "ashok", "city": "chennai"}
    do ..pyKWArgs(kwargs...)
}

ClassMethod pyKWArgs(name, city, dob = "") [ Language = python ]
{
    print(name, city, dob)
}

// output
LEARNING>do ##class(MyLearn.EmbeddedPythonUtils).KWArgs()
ashok chennai

I will cover the global, routines and SQL in next article

1 Comment
讨论 (1)1
登录或注册以继续
公告
· 九月 12, 2024

[Video] Identifying Useful Components for Your Generative AI Application

Hi, Community!

What components and libraries can you add to your retrieval-augmented generation (RAG) applications? Find out in this video:

Identifying Useful Components for Your Generative AI Application

In this interview, InterSystems Sales Engineer @Elijah Cotterrell introduces the components you can leverage on top of your RAG applications, including:

  • Agents
  • Hugging Face data sets
  • Embedding models

Continue learning how to develop generative AI applications (learning path, 2h).

讨论 (0)1
登录或注册以继续
文章
· 九月 12, 2024 阅读大约需 4 分钟

Python IRIS Nativo

Olá comunidade

Nós experimentamos anteriormente o Python embutido em IRIS; no entanto, eu ainda não tive a oportunidade de implementar IRIS usando Python nativo. Nesse artigo, vou percorrer os passos que eu usei para começar a aprender e implementar IRIS dentro da fonte Python. Eu também gostaria de agradecer @Guillaume Rongier@Luis Angel Pérez Ramos pela ajuda resolvendo os problemas que encontrei durante minha recente instalação PIP de IRIS no Python, que eu habilitei para funcionar adequadamente.

Vamos começar a escrever IRIS em Python.

Em primeiro lugar, você precisa instalar o arquivo intersystems_irispython-3.2.0-py3-none-any.whl do repositório github. Eu fiz o download e baixei na minha máquina windows.

py -m pip install intersystems_irispython-3.2.0-py3-none-any.whl

Verifiquei que os pacotes estão instalados na minha máquina executando py -m pip list

intersystems-irispython 3.2.0
iris                    0.0.5

Agora estamos prontos para começar a escrever o Python. Eu criei um arquivo .py e importei um pacote iris em cima da classe.

Agora, vamos estabelecer a conexão ao IRIS usando o método de conexão e criar e usar o objeto de conexão para instanciar o objeto iris.IRIS usando o "createIRIS" e esse é o  passo crucial para seguir com operações mais adiante.

import iris
impor time

args = {'hostname':'127.0.0.1', 'port':1972,'namespace':'LEARNING', 'username':'_SYSTEM', 'password':'SYS'}

try:
    """
    some other ways instead of kwargs
    conn = iris.connect(hostname='127.0.0.1', port=1972, namespace='LEARNING',username='_SYSTEM',password='SYS')
    """
    conn = iris.connect(**args)
    # A new IRIS object that uses the given connection.
    irispy = iris.createIRIS(conn)

    print('connected!')
except Exception as e:
    # Handling the exception and printing the error
    print(f"An error occurred: {e}")
    

Agora, vamos falar sobre os métodos para COS e globais.

Uma vez que você criou com sucesso um objeto IRIS, agora está pronto para usar várias operações.

set : Essa função é usada para definir os valores de globais na base de dados IRIS.

1. O primeiro parâmetro é o valor

2. Segundo parâmetro é o nome da global

3. *args - o terceiro parâmetro são subscritos.

def set_global(value=None,gbl=None,*args):
    #set method is in _IRIS from iris package
    irispy.set('set from irispy','mygbl','a',str(time.time()))
    print('global set done!')

set_global()

 

kill: Essa função é usada para deletar a global da base de dados

def kill_global():
    irispy.kill('mygbl')
    print('global kill done!')

IsDefined: o mesmo que $data: verifica se existe

def data_isDefined():
    # equal to $data
    print(irispy.isDefined('mygbl','a')) # o/p 10
    print(irispy.isDefined('mygbl','a','1724996313.480835')) # o/p 1

nextSubscript: Igual a $Order

irispy.nextSubscript(0,'mygbl','a')

tStart, tCommit e tRollback: o mesmo que TStart, TCommit, TRollback

def global_transaction_commit():
    irispy.tStart()
    print(irispy.getTLevel())
    irispy.set('set from irispy','mygbl','trans',str(time.time()))
    irispy.tCommit()

def global_transaction_rollback():
    irispy.tStart()
    print(irispy.getTLevel())
    irispy.set('set from irispy','mygbl','trans1',str(time.time()))
    irispy.tRollback() # tRollbackOne()

 

lock e unlock: por default lock incremental/lock exclusivo

def global_lock():
    #default exclusive lock
    s = irispy.lock('',1,'^mygbl')
    time.sleep(10) # verify the lock in locktab
    irispy.unlock('','^mygbl')
    
def global_shared_lock():
    s = irispy.lock('S',1,'^mygbl')
    time.sleep(10)
    irispy.unlock('S','^mygbl')

node: nó de subscrito da árvore mesmo que $Order

def node_traversal():
    # subscript level traversal like $Order
    for mrn in irispy.node('^mygbl'):
         for phone in irispy.node('^mygbl',mrn):
            print(f'patient mrn {mrn} and phone number: {phone}')
            
"""
o/p
patient mrn 912 and phone number: 3166854791
patient mrn 991 and phone number: 78050314
patient mrn 991 and phone number: 9128127353
"""

O nó, valor de árvore e definições de classe e seus membros estão cobertos no próximo artigo.

Você pode ver a referência na documentação para todas as funções.

讨论 (0)1
登录或注册以继续
文章
· 九月 12, 2024 阅读大约需 1 分钟

QuinielaML - Predicciones de la 7ª jornada de la Quiniela

Después del parón de selecciones tenemos nueva jornada de Primera y Segunda División en la Quiniela del próximo fin de semana. Estos son los partidos que forman parte de la jornada: 

Estas son las predicciones para Primera División:

Y para la Segunda División:

Lo que nos deja la siguiente Quiniela:

¡Pues ya tenemos la Quiniela ganadora!

讨论 (0)1
登录或注册以继续
文章
· 九月 12, 2024 阅读大约需 3 分钟

Crear, Listar, Subir y Descargar archivos y carpetas de red usando el protocolo SMB y la interoperabilidad de IRIS

Samba es el estándar para la interoperabilidad de servicios de archivos entre Linux, Unix, DOS, Windows, OS/2 y otros sistemas operativos. Desde 1992, Samba ha proporcionado servicios de archivos seguros, estables y rápidos para todos los clientes (sistemas operativos y programas) utilizando el protocolo SMB/CIFS. Los administradores de red han utilizado SAMBA para crear carpetas de red compartidas que permiten a los empleados de la empresa crear, editar y visualizar archivos corporativos como si estuvieran en sus ordenadores localmente, aunque estos archivos se encuentren físicamente en un servidor de archivos en red. Es posible crear una carpeta de red en Linux y verla como una carpeta compartida en Windows, por ejemplo.

Actualmente, los conectores de IRIS no soportan el acceso ni la escritura de archivos y carpetas remotas usando el protocolo SMB, por lo que es necesario usar FTP. Sin embargo, ahora contamos con Python, que dispone de la librería "smbprotocol" (https://pypi.org/project/smbprotocol). Basado en esta librería, se ha creado una aplicación de interoperabilidad (producción) para listar, grabar y eliminar archivos y carpetas utilizando el protocolo SMB. Ahora, vuestras aplicaciones IRIS pueden escribir o acceder fácilmente a archivos de red. La aplicación se llama "samba-iris-adapter" (https://openexchange.intersystems.com/package/samba-iris-adapter).

 

Instalación de la aplicación

Instalación: ZPM

1. Abrir un Namespace de IRIS con la interoperabilidad habilitada. Abrir la Terminal y ejecutar:

USER>zpm "install samba-iris-adapter"

Instalación: Docker

1. Clonad/haced git pull del repositorio en cualquier directorio local.

$ git clone https://github.com/yurimarx/samba-iris-adapter.git

2. Abrid la terminal en este directorio y ejecutad:

$ docker-compose build

3. Ejecutad el contenedor de IRIS con vuestro proyecto:

$ docker-compose up -d

Cómo iniciar la aplicación

1. Id a Interoperabilidad > Configurar > Credenciales:

2. Estableced las credenciales y guardad con estos valores:

ID: SambaCredentials
User name: bob
Password: bobspasswd 
Credentials

3. Abrid la producción http://localhost:52795/csp/user/EnsPortal.ProductionConfig.zen?PRODUCTION=dc.samba.SambaProduction e iniciarla.

4. Id a vuestra aplicación cliente REST y utilizad estas operaciones REST (con autenticación básica y credenciales _SYSTEM/SYS):

5. Cread una nueva Carpeta Remota: POST http://localhost:52795/csp/samba/CreateFolder con el cuerpo JSON: {"Folder":"samplefolder"}

6. Para enviar un archivo a una Carpeta Remota: POST http://localhost:52795/csp/samba/CreateFile/samplefolder con form-data seleccionado para enviar un archivo multipart. El nombre del archivo multipart es "file" y en el valor seleccionad cualquier archivo de vuestro ordenador. Consultad esta imagen con un ejemplo usando Postman:

7. Listad los archivos dentro de una Carpeta Remota: GET http://localhost:52795/csp/samba/ListFilesIntoFolder/samplefolder:

8. Descargad el archivo: POST http://localhost:52795/csp/samba/DownloadFile con el cuerpo JSON: {"Folder":"samplefolder", "Filename":"cat.jpg"}

9. Ved los mensajes de las producciones en http://localhost:52795/csp/user/EnsPortal.ProductionConfig.zen?$NAMESPACE=USER&$NAMESPACE=USER& > Pestaña Mensajes > haced clic en la Sesión:

10. Comprobad la nueva carpeta y archivo dentro de la carpeta /mnt2 en la instancia Docker de Samba:

¡Disfrutadlo!

讨论 (0)1
登录或注册以继续