Unificando o Embedded Python e a Native API com o `iris-embedded-python-wrapper`

Ao desenvolver aplicações Python com o InterSystems IRIS, você pode rapidamente acabar com vários contextos de execução:
- Python iniciado diretamente pelo IRIS com Embedded Python;
- um processo
python3comum que carrega as bibliotecas Embedded Python de uma instalação local do IRIS; - uma aplicação Python externa que se conecta ao IRIS através do driver nativo oficial.
Esses três casos são úteis, mas eles não se comportam exatamente da mesma forma para imports, configuração do sistema, APIs de objetos e acesso SQL. O projeto iris-embedded-python-wrapper fornece uma fachada Python estável para reduzir essas diferenças e manter um único ponto de entrada: import iris.
O Problema
Em um projeto Python construído em torno do IRIS, o mesmo código pode precisar ser executado em vários ambientes:
- em um terminal IRIS com
iris python iris, ouiris session irisseguido de:py; - em um script Python local iniciado com
python3; - em um serviço Python remoto que se conecta a uma instância IRIS.
Sem uma camada de abstração, vários detalhes frequentemente precisam ser tratados separadamente:
- o módulo
irisdo Embedded Python só está disponível quando o runtime do IRIS é carregado corretamente; - o SDK nativo também expõe um pacote
iris, o que pode criar colisões ou imports ambíguos; iris.cls(...)e conexões DB-API não seguem exatamente o mesmo fluxo nos modos embedded e remoto;- em Linux e macOS, os caminhos das bibliotecas dinâmicas precisam ser preparados antes do processo Python iniciar;
- valores de fronteira como SQL
NULLe strings vazias podem ser representados de forma diferente dependendo do backend.
O objetivo deste wrapper é permitir que a aplicação declare claramente seu contexto de execução enquanto mantém o código de negócio semelhante entre os modos embedded e native.
O Que o Wrapper Fornece
O pacote fornece uma fachada import iris que mantém disponíveis os pontos de entrada mais comuns:
iris.cls(...)para acessar classes IRIS;iris.connect(...)para configurar ou abrir uma conexão dependendo do contexto;iris.dbapipara acesso SQL no estilo PEP 249;iris.runtimepara inspecionar e controlar explicitamente o modo ativo.
Os modos suportados são:
| Modo | Descrição | Exemplo |
|---|---|---|
embedded-kernel |
Python é iniciado pelo IRIS | iris python iris ou :py |
embedded-local |
python3 carrega as bibliotecas Embedded Python de uma instalação local IRIS |
IRISINSTALLDIR, iris.connect(path=...) |
native-remote |
Python se conecta a uma instância IRIS remota | driver nativo oficial intersystems-irispython |
unavailable |
nenhum backend IRIS está disponível ainda | configuração necessária antes do uso |
Instalação
O pacote pode ser instalado com pip:
pip install iris-embedded-python-wrapper
O projeto depende do driver oficial:
intersystems-irispython>=5.0.0
Para o modo embedded, você também precisa de uma instalação local do InterSystems IRIS. Para acessar o modo embedded a partir de um processo Python externo, o serviço %Service_CallIn deve estar habilitado.
Exemplo: Usando Embedded Python
Em um shell Embedded Python iniciado pelo IRIS:
iris python iris
ou a partir de uma sessão IRIS:
USER>:py
você pode importar iris normalmente:
import iris
print(iris.system.Version.GetVersion())
print(iris.runtime.state)
Nesse contexto, iris.runtime.state deve retornar:
'embedded-kernel'
Se você quiser forçar o wrapper a partir de um diretório local do projeto:
PYTHONPATH=/path/to/iris-embedded-python-wrapper iris python iris
Exemplo: Carregando IRIS a partir de um python3 Local
O modo embedded-local permite executar um script Python comum enquanto utiliza as bibliotecas Embedded Python de uma instalação IRIS.
No Linux:
export IRISINSTALLDIR=/opt/iris
export LD_LIBRARY_PATH=$IRISINSTALLDIR/bin:$LD_LIBRARY_PATH
python3 my_script.py
No macOS:
export IRISINSTALLDIR=/opt/iris
export DYLD_LIBRARY_PATH=$IRISINSTALLDIR/bin:$DYLD_LIBRARY_PATH
python3 my_script.py
O wrapper também permite declarar explicitamente o caminho da instalação IRIS:
import iris
iris.connect(path="/opt/iris")
obj = iris.cls("Ens.StringRequest")._New()
obj.StringValue = "hello from embedded-local"
Ponto importante: em Unix, iris.connect(path=...) pode configurar os caminhos Python em tempo de execução, mas não pode corrigir retroativamente a resolução de bibliotecas dinâmicas se o processo Python já tiver iniciado sem o LD_LIBRARY_PATH ou DYLD_LIBRARY_PATH corretos.
Exemplo: Mantendo iris.cls(...) no Modo Native Remoto
Com o SDK nativo, o código remoto normalmente usa um handle IRIS explícito:
import iris
conn = iris.connect("localhost", 1972, "USER", "SuperUser", "<password>")
db = iris.createIRIS(conn)
req = db.classMethodValue("Ens.StringRequest", "%New")
db.set(req, "StringValue", "hello")
value = db.get(req, "StringValue")
Com o wrapper, você pode vincular a conexão nativa uma única vez e manter uma sintaxe próxima do Embedded Python:
import iris
conn = iris.connect("localhost", 1972, "USER", "SuperUser", "<password>")
iris.runtime.configure(native_connection=conn)
req = iris.cls("Ens.StringRequest")._New()
req.StringValue = "hello"
value = req.StringValue
O proxy nativo converte o primeiro _ em %, o que permite escrever _New() em Python para chamar %New.
Controlando Explicitamente o Runtime
iris.runtime é a fonte de verdade do wrapper para o contexto ativo.
import iris
ctx = iris.runtime.get()
print(ctx.mode)
print(ctx.state)
print(ctx.embedded_available)
Propriedades úteis incluem:
iris.runtime.mode: política selecionada, por exemploauto,embeddedounative;iris.runtime.state: estado detectado, por exemploembedded-kernel,embedded-local,native-remoteouunavailable;iris.runtime.embedded_available: indica se o backend embedded está utilizável;iris.runtime.iris: handle IRIS nativo vinculado ao runtime, se disponível;iris.runtime.dbapi: conexão DB-API explicitamente vinculada, se disponível.
Você também pode forçar um modo:
import iris
iris.runtime.configure(mode="embedded")
ou redefinir para detecção automática:
iris.runtime.reset()
Acesso SQL com iris.dbapi
O wrapper expõe uma fachada DB-API compatível com o uso comum:
connect();cursor();execute();fetchone(),fetchmany(),fetchall();commit(),rollback(),close();- exceções PEP 249 como
InterfaceError,OperationalError, etc.
No modo embedded:
import iris
conn = iris.dbapi.connect(mode="embedded")
cur = conn.cursor()
cur.execute("SELECT Name FROM Sample.Person")
rows = cur.fetchall()
cur.close()
conn.close()
No modo embedded-local com caminho explícito:
import iris
conn = iris.dbapi.connect(path="/opt/iris", namespace="USER")
cur = conn.cursor()
cur.execute("SELECT 1")
print(cur.fetchone())
No modo native remoto:
import iris
conn = iris.dbapi.connect(
mode="native",
hostname="localhost",
port=1972,
namespace="USER",
username="SuperUser",
password="<password>",
)
cur = conn.cursor()
cur.execute("SELECT 1")
print(cur.fetchone())
No modo auto, o wrapper escolhe o backend com base nos argumentos fornecidos e no estado de iris.runtime. Por exemplo, se você fornecer hostname, port, namespace, username e password, a conexão será direcionada para o driver nativo.
O wrapper também normaliza alguns casos embedded para aproximar o comportamento da DB-API nativa:
- SQL
NULLtorna-se PythonNone; - uma string SQL vazia torna-se
""; Nonepassado como parâmetro permanece SQLNULL;""passado como parâmetro permanece uma string SQL vazia.
Vinculando um Ambiente Virtual ao Embedded Python
O projeto fornece dois comandos práticos:
bind_iris
unbind_iris
bind_iris procura a biblioteca Python do ambiente virtual atual, atualiza a configuração do Embedded Python do IRIS e cria um backup do arquivo iris.cpf.
Exemplo:
python3 -m venv .venv
. .venv/bin/activate
pip install iris-embedded-python-wrapper
bind_iris
Dependendo da plataforma e da configuração do IRIS, privilégios de administrador do IRIS podem ser necessários. No Windows, reiniciar a instância IRIS pode ser necessário após alterar a configuração.
Quando Você Deve Usar Este Wrapper?
Este wrapper é útil se você quiser:
- escrever código Python para IRIS que possa ser executado em modo embedded ou remoto;
- reduzir diferenças entre Embedded Python e a Native API;
- tornar o modo de execução observável através de
iris.runtime; - usar uma única fachada DB-API no código da aplicação;
- simplificar a configuração de ambientes virtuais para Embedded Python;
- testar caminhos embedded e remotos com mais facilidade.
Ele não substitui o InterSystems IRIS nem o SDK nativo oficial. É uma camada de conveniência construída sobre esses componentes para tornar o código da aplicação mais portátil.
Recursos
- Projeto GitHub: https://github.com/grongierisc/iris-embedded-python-wrapper
- Documentação do projeto: https://github.com/grongierisc/iris-embedded-python-wrapper/blob/master/README.md
- Instalação:
pip install iris-embedded-python-wrapper - Licença: MIT
Conclusão
iris-embedded-python-wrapper fornece uma fachada simples sobre os principais modos de execução Python do InterSystems IRIS. O principal benefício é poder escrever:
import iris
e então decidir explicitamente se o código será executado em Embedded Python, no modo embedded-local ou através de uma conexão native remota. Para aplicações que precisam migrar de um modo para outro, ou para equipes que desejam compartilhar mais código entre scripts locais, jobs embedded e serviços Python externos, essa abordagem remove muito ruído técnico.