Article
· Sep 13 7m read

Embedded python in InterSystems IRIS Part-2

In the previous article. Practices of class members and their execution within embedded Python. We will now turn our attention to the process of switching namespaces, accessing global variables , traversing and routine executions within embedded Python.

Before proceeding to the other functions. let us briefly review the execute function within the iris package. This function is exceptionally beneficial for executing the arbitrary ObjectScript functions and class invocation.

>>> b = iris.execute('return $Piece("test^aaaa","^",2)')
>>> b
'aaaa'
>>> b = iris.execute('return $Extract("123456",2,5)')
>>> b
'2345'
>>> b = iris.execute('return $Length(123456)')
>>> iris.execute('write ##Class(%SYSTEM.SYS).NameSpace()')
LEARNING>>>
>>> b = iris.execute('return ##Class(%SYSTEM.SYS).NameSpace()')
>>> b
'LEARNING'

 

Let us begin!

4. Switch Namespaces

Switching namespaces during execution is often necessary. However, unlike in IRIS, direct switching of namespaces within embedded Python is not feasible. Therefore, it is essential to utilize existing class definitions or to create a wrapper method to facilitate the switching of namespaces.  

ClassMethod SwitchNM() [ Language = python ]
{
    import iris
    print(iris.cls('%SYSTEM.SYS').NameSpace())
    print(iris.system.Process.SetNamespace("USER"))
    try:
        iris.cls('User.EmbeddedPython').pyGetTemplateString()
    except RuntimeError as e:
        print("Wrong NameSpace",e)
}

 

5. Global

To utilize the capabilities of global for data traversal or to retrieve information from legacy global systems directly, rather than through SQL or objects within embedded Python, one can access it directly by employing the gref function from the iris package. To set or get global values, the gref function can be utilized to establish a reference to the global variable and directly assign values within Python.

 
iris.gref

5.1 Set global values

ClassMethod SetGlobal() [ Language = python ]
{
import iris
#create a global reference
g = iris.gref('^mygbl') 
g[1],g[2]='Mon','Tue'
g["95752455",1]=iris.execute('return $LFS("Ashok,55720,9639639639,test@gmail.com",",")')
g["85752400",1]=iris.execute('return $LB("Test","9517539635","t@gmail.com")')
g["test","c1"]=iris.execute('return ##Class(MyLearn.EmbeddedPython).executeAndGetResult()') # method wil return some listbuild values
# declare values by using set function
g.set([3],'Wed')
g.set([3,1,1],'Test multilevel')
}

5.2 get global values
Fetch the global values from python directly by using the subscripts or get method.

ClassMethod GetGlobal() [ Language = python ]
{
    import iris
    #gets a global reference
    g = iris.gref('^mybgl') 
    # get values
    print(g[3,1,1])
    print(g.get([2,1]))
    print(g["95752455",1])
}

5.3 Traversal 

order - Traversing the global is essential for collecting multiple level of data's from global. This embedded Python  order functions similarly to the $Order command, utilizing the order function from the iris.gref. Initially, it is necessary to establish a reference to the global entity that requires traversal.

Single subscript level traversal

ClassMethod DollarOrder() [ Language = python ]
{
    import iris
    g = iris.gref('^MyLearn.EmbeddedPythonD') # I use my persistent class global
    key = ''
    while True:
        key = g.order([key])
        if key == None:
            break
        print(f'{key} {g.get([key])}')
}

Multi subscript level traversal

 
global
ClassMethod DollarOrderMultiLevel() [ Language = python ]
{
 import iris
 g = iris.gref('^mygbl')
 key1= ''
 while True:
 	key1 = g.order([key1])
 	if key1== None:
 		break
 	key2 = ''
 	while True:
 		key2 = g.order([key1,key2])
 		if key2 == None:
 			break
 		value = g.get([key1,key2])
 		print(key1,key2,value)
}

query - query function from the iris.gref similarly $query. This function is collects all the global values in to tuples. the tuple result contains the id(s) in list and values is the next tuple. You can refer the below tuple sample 

 
tuple
ClassMethod DollarQuery() [ Language = python ]
{
 	import iris
 	g = iris.gref('^mygbl')
 	key = g.query()#this will return tuples of all the subscripts
 	for x in key:
 		print(x) # output (['3', '1', '1'], 'Test multilevel')
}

data - this data function Check whether the given subscript is exist in the global and return the $data values by using the data function

ClassMethod DollarData() [ Language = python ]
{
    import iris
    g = iris.gref('^mygbl')
    key1= ''
    print(g.data([1]))
}

 

6. Routines

Furthermore, it is essential to implement the class members. We must execute the routines as part of the implementation for legacy codebase systems and other related situations. Consequently, there exists a dedicated function within the iris library package that allows for the invocation of routines from embedded python through the use of the routine function.

 
myirispython.mac
ClassMethod RunRoutines() [ Language = python ]
{
    import iris
    iris.routine('^myirispython')
    iris.routine('add^myirispython',1,2) # same as write $$add^myirispython(1,2)
}

Additionally, you can execute the routine by using execute function as well. iris.execute('do ^myirispython')

note: If the routine is not found 
>>> iris.routine('^myirispythonT')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
RuntimeError: Routine not found

Will continue the other topics in the next article.

Discussion (3)1
Log in or sign up to continue

Hello @Guillaume Rongier

Thanks for the feedback! I go over your pretty useful article. I just write python code inside the ObjectScript itself by using language mode because of it's small code snippets. I actually facing some issues while writing IRIS in native python script.

From my pervious community question. First I install this intersystems_irispython-3.2.0-py3-none-any.whl in python and there is no cls, execute, routine, gref, ref or other IRIS script functions available.

As you recommend from the post. I install the official driver  https://github.com/intersystems-community/intersystems-irispython/releases/download/3.8.0/intersystems_iris-3.8.0-py3-none-any.whl file and I could use the IRIS functions for embedded python cls, execute, routine, gref, ref etc...

However, I got this ImportError: DLL load failed while importing pythonint: The specified module could not be found." error while executing the .py scripterror while executing my script

script is nothing but simple class method invocation.

import iris
def Execute_Classmethod():
    print(iris.cls('MyLearn.EmbeddedPython').test1())

Execute_Classmethod()
 

anyway when I keep my native python scripts under "IRISinstalldirectory\mgr\python" and import my code as module and it's working because it's running inside the IRIS not using the python "driver" 

ClassMethod CallPyscripts()
{
    set ap = "mypyap"
    set pyImport = ##class(%SYS.Python).Import(ap)
    set builtin = $SYSTEM.Python.Builtins()
    do builtin.help(pyImport)
    write pyImport.irisversion,!
    write pyImport."Execute_Classmethod1"()
}
#__init__.py
import iris
from .irisembdpyth2024 import *

irisversion = iris.execute('return $zv')

# irisembdpyth2024.py file
import iris

def Execute_Classmethod1():
    print(iris.cls('MyLearn.EmbeddedPython').test1())