Article
· Nov 18 8m de lecture

Embedded Python dans InterSystems IRIS

Bonjour la communauté,

Dans cet article, je vais décrire et illustrer le processus de mise en œuvre d'ObjectScript au sein de Embedded Python. Cette discussion fera également référence à d'autres articles relatifs à Embedded Python, et répondra aux questions qui ont été utiles à mon apprentissage.

Comme vous le savez peut-être, l'intégration des fonctionnalités de Python dans IRIS est possible depuis un certain temps. Cet article se concentrera sur la manière dont ObjectScript peut être incorporé de manière transparente à Embedded Python.

Essentiellement, Embedded Python sert d'extension qui permet une écriture et une exécution indépendantes. Il permet l'intégration transparente du code Python avec ObjectScript et vice versa, permettant aux deux de s'exécuter dans le même contexte. Cette fonctionnalité améliore considérablement les capacités de votre implémentation.

Pour commencer, vous devez spécifier le langage de votre code Python dans la définition de la classe en utilisant le mot-clé "language" [language = "python"]. Une fois cette étape franchie, vous êtes prêt à écrire votre code Python.

import iris - Ce paquet iris est une bibliothèque Python essentielle qui facilite la communication avec les classes, routines, globales et SQL de l'API native d'InterSystems. Ce paquet est facilement disponible par défaut. Quoi qu'il en soit, il est nécessaire d'importer ce paquet au début de votre code Python si vous souhaitez interagir avec IRIS.

Quelques notes importantes avant d'écrire

  • Vous pouvez utiliser une variable spéciale python __name__ pour référencer le nom de classe dans la définition de classe.
  • Use _ for %Methods ex: %New  == _New , %OpenId == _OpenId

Commençons

Mise en œuvre des éléments d'une classe en Python intégré

1.  Objets et Propriétés

Cette partie est essentielle car elle couvre le processus d'initialisation d'un nouvel objet, la modification des valeurs des objets existants et la configuration des propriétés dans des contextes statiques et dynamiques. Créez votre propre définition de classe et utilisez les propriétés littérales simples

1.1 initialisation new d'un nouvel objet / Modification d'un objet existant

Utilisez _New pour initialiser un nouvel objet et _OpenId(id) pour modifier l'objet existant

ClassMethod SaveIRISClsObject() [ Language = python ]
{
 #cette méthode appelle la méthode de rappel %OnNew et récupère l'objet
 import iris
 try:
     iris_obj =  iris.cls(__name__)._New()
     if not iris.cls(__name__).IsObj(iris_obj):
      #IsObj est la méthode wrapper d'objectscript : elle contient $Isobject()
         raise ReferenceError('Object Initlize Error')
 except ReferenceError as e:
     print(e)
     return
 #définition des propriétés de l'objet et enregistrement des valeurs 
 iris_obj.Name = 'Ashok'
 iris_obj.Phone = 9639639635
 status = iris_obj._Save()
 print(status)
 return status
}

1.2 Accès  aux propriétés

Avant de procéder à la partie sur les propriétés, il est important de noter que le type de données IRIS diffère des types de données Python et que, par conséquent, les types de données de collecte IRIS ne peuvent pas être utilisés directement dans Python. Pour résoudre ce problème, InterSystems a proposé une solution complète pour convertir les types de données IRIS en formats compatibles avec Python, tels que les listes, les ensembles et les tuples. Pour ce faire, il suffit d'importer le module "builtins" dans la base de code IRIS, en utilisant les méthodes de classe ##class(%SYS.Python).Builtins() ou en définissant les builtins = ##class(%SYS.Python).Import("builtins"). Je reviendrai sur ce point dans les prochaines parties.

J'utilise donc cette méthode pour convertir les propriétés $LB en liste  python afin d'accéder aux propriétés au moment de l'exécution en 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 Définition des propriétés au moment de l'exécution.

J'utilise ce dictionnaire python pour désigner ma propriété en tant que clé et, avec les valeurs de propriété correspondantes servant de valeurs dans ce dictionnaire. Vous pouvez vous référer au code fourni ci-dessous et à l'article de la communauté concernant ce jeu de propriétés .

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 Contexte de partage d'objets

Comme j'ai indiqué précédemment, Python et ObjectScript opèrent dans le même contexte de mémoire et partagent des objets. Cela implique que vous pouvez créer ou ouvrir un objet dans la classe InCache et, par la suite, le définir ou le récupérer dans la classe Python.

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. La méthode de classe et les méthodes

3.1 La méthode de classe

L'invocation des méthodes et des fonctions de classe est très utile pour l'exécution du code de script d'objet.

Il est possible d'invoquer la méthode de classe en tant qu'appel statique,  par exemple: Do ..Test() 

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


Invocation de la méthode de Classe au moment de l'exécution Set method="Test" Do $ClassMethod(class, method, args...)

ClassMethod InvokeClassMethodsRunTime(classMethod As %String = "Test") [ Language = python ]
{
 import iris
 clsMethodRef = getattr(iris.cls(__name__), classMethod) # renvoie la référence de la méthode
 print(clsMethodRef()) 
}

3.2  Méthodes

Invocation des méthodes d'instance est identique au format "script d'objet". Dans le code ci-dessous, j'ai d'abord créé l'objet, puis j'ai appelé la méthode d'instance avec des paramètres.

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

3.3  Transmission d'arguments par valeur et  par référence entre python et ObjectScript

Fondamentalement, la transmission des arguments est  inévitable entre les fonctions et elle en sera de même entre ObjectScript et Python

3.4  Transmission d'arguments par valeur - C'est comme d'habitude la transmission d'arguments par valeur

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

/// transmission par valeur de python au script d'objet
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 Transmission par référence- C'est au contraire de la transmission par valeur. Comme Python ne supporte pas nativement l'appel par référence, il faut donc utiliser la fonction iris.ref()  dans le code Python pour que la variable devienne une référence. à savoir, la référence . A ma connaissance, il n'y a pas d'effets du côté du script d'objet concernant les variables de type pass-by-reference (transmission par référence), même lorsque ces variables sont modifiées en Python. Par conséquent, les variables Python seront affectées par ce mécanisme de pass-by-reference lorsque les méthodes du script d'objet seront invoquées

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)
    #transmission par référence de la date de naissance, ville
    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"
}

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


3.5 **kwargs- Il existe un support supplémentaire pour passer les arguments de mot-clé python (**kwargs) à partir d'un script d'objet. InterSystems IRIS n'ayant pas de concept d'arguments de mot-clé, il faut créer un  %DynamicObject pour contenir les paires mot-clé/valeur et passer les valeurs en tant qu' Args...de syntax

J'ai créé le dynamicObject  "name""ashok""city""chennai"}et j'y ai inséré les paires clé-valeur requises, que j'ai ensuite transmises au code python.

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

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

// résultat
LEARNING>do ##class(MyLearn.EmbeddedPythonUtils).KWArgs()
ashok chennai

Je décrirai les globales, les routines et SQL dans le prochain article

Discussion (0)2
Connectez-vous ou inscrivez-vous pour continuer