Artigo
· jan 23 7min de leitura

Python Embutido no InterSystems IRIS

Olá comunidade,

Neste artigo, vou descrever e ilustrar o processo de implementação do ObjectScript dentro do Python embutido. Esta discussão também fará referência a outros artigos relacionados ao Python embutido, bem como abordará questões que foram benéficas para a minha jornada de aprendizado.

Como você sabe, a integração de recursos Python dentro do IRIS tem sido possível há algum tempo. Este artigo se concentrará em como incorporar perfeitamente o ObjectScript com o Python embutido.

Essencialmente, o Python embutido serve como uma extensão que permite a escrita e execução independentes. Ele permite a integração perfeita do código Python com o ObjectScript e vice-versa, permitindo que ambos sejam executados dentro do mesmo contexto. Essa funcionalidade aprimora significativamente as capacidades da sua implementação.

Para começar, você deve especificar a linguagem para o seu código Python dentro da definição da classe usando a palavra-chave "language" [language = "python"]. Feito isso, você está preparado para escrever o seu código Python.

import iris - O pacote iris é uma biblioteca Python vital que facilita a comunicação com as classes nativas, rotinas, globais e SQL do InterSystems. Este pacote está prontamente disponível por padrão. De qualquer forma, é necessário importar este pacote no início do seu código Python se você for interagir com o IRIS.

Algumas notas importantes antes de escrever

  • Você pode usar a variável especial do Python __name__ para se referir ao nome da classe dentro da definição da classe.
  • Use _ para %Methods ex: %New  == _New , %OpenId == _OpenId

Vamos começar

Implementação de membros de classe em Python Embutid

1.  Objetos e Propriedades

Esta seção é essencial, pois abordará o processo de inicialização de um novo objeto, alteração dos valores de objetos existentes e configuração de propriedades em contextos estáticos e dinâmicos. Crie sua própria definição de classe e use as propriedades literais simples

1.1 Inicializar novo Objeto / Modificar objeto existente

Use _New para iniciar um novo objeto e _OpenId(id) para editar o objeto existente

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 Accessando propriedades

Antes de iniciar a seção sobre propriedades, é importante observar que o tipo de dados IRIS difere dos tipos de dados Python, e portanto, os tipos de dados de coleção IRIS não podem ser utilizados diretamente dentro do Python. Para solucionar isso, a InterSystems ofereceu uma solução abrangente para converter tipos de dados IRIS em formatos compatíveis com Python, como listas, conjuntos e tuplas. Isso pode ser alcançado importando o módulo "builtins" dentro da base de código IRIS, utilizando os métodos de classe ##class(%SYS.Python).Builtins() ou definindo builtins = ##class(%SYS.Python).Import("builtins").
Abordarei isso nas próximas seções. 

Então, eu uso esse métood para converter as propriedades $LB em lista  python para acessar as propriedades em tempo de execução no 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 Defina propriedades em tempo de execução

Utilizo este dicionário Python para designar minha propriedade como chave e, com os valores de propriedade correspondentes servindo como valores dentro desse dicionário. Você pode consultar o código fornecido abaixo e a postagem da comunidade relacionada a essa configuração de propriedade.

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 Contexto de objetos compartilhados

Como mencionado anteriormente, tanto Python quanto ObjectScript operam dentro do mesmo contexto de memória e compartilham objetos. Isso significa que você pode criar ou abrir um objeto na classe InCache e posteriormente definir ou recuperá-lo na 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.  Parâmetros

Obtenha o par chave-valor arbitrário do parâmetro usando o método _GetParameter. Consulte o útil post da comunidade.

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

3. Class Method e Methods

3.1 Class Method

A invocação de métodos e funções de classe é altamente benéfica para a execução do código ObjectScript.

Invoque o método de classe como uma chamada estática, por exemplo: Do ..Test() 

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


Invoque o método de classe em tempo de execução 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

A invocação dos métodos de instância é feita da mesma forma que no formato 'ObjectScript'. No código abaixo, primeiro inicializo o objeto e, em seguida, chamo o método de instância com parâmetros.

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

3.3  Passagem de argumentos por valor e por referência entre Python e ObjectScript

Basicamente, a passagem de argumentos é inevitável entre funções e seguirá o mesmo comportamento entre ObjectScript e Python.

3.4 Passagem por valor - É a passagem por valor usual.

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 Passagem por referência Diferentemente da passagem por valor. Como o Python não suporta nativamente a passagem por referência, é necessário utilizar o iris.ref() no código Python para tornar a variável uma referência. Consulte a referência. Pelo que sei, não há efeitos no lado ObjectScript em relação a variáveis passadas por referência, mesmo quando essas variáveis são modificadas em Python. Consequentemente, as variáveis Python serão afetadas por esse mecanismo de passagem por referência quando os métodos do ObjectScript forem invocados.

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- Existe suporte adicional para passar argumentos de palavra-chave Python (**kwargs)a partir do ObjectScript. Como o InterSystems IRIS não possui o conceito de argumentos de palavra-chave, é necessário criar um   %DynamicObject para armazenar os pares chave-valor e passar os valores usando a sintaxe Args...

Eu criei o dynamicObject "name""ashok""city""chennai"}e nele defini os pares chave-valor necessários, passando-o posteriormente ao código Python.

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

No próximo artigo, tratarei de assuntos como variáveis globais, rotinas e SQL.

Discussão (0)1
Entre ou crie uma conta para continuar