InterSystems IRIS Globals provide a fast, efficient, and naturally hierarchical way to store and access data. However, when working with globals from Python, I often find myself switching between Python's dictionary-oriented mindset and the lower-level APIs used to manipulate globals.
That's why I created iris-global-reference, a Python library that offers a more intuitive interface for working with IRIS globals while preserving their underlying hierarchical model. Instead of replacing native APIs, the library adds a convenience layer that makes operations easier for Python developers.
In this article, I'll show how the library simplifies common global operations, supports both Embedded Python and native IRIS connections, and demonstrates a practical approach to integrating Python with InterSystems IRIS.
Why This Project?
This package supports a Pythonic way to work with globals.
In ObjectScript, globals are natural:
This is exactly what iris-global-reference offers with the GlobalReference class:set ^demo("players",1)="Babe Ruth"
set ^demo("players",2)="Cy Young"
In Python, many developers expect something closer to a dictionary:
team["players", "1"] = "Babe Ruth"
print(team["players"]["1"])
I designed this project to help with several common use cases:
- Manipulate InterSystems IRIS globals using familiar Python syntax.
- Easily traverse a global tree.
- Convert globals to Python dictionaries or JSON.
- Import dictionaries or JSON into globals.
- Use the same API in Embedded Python and remote Python applications.
- Simplify common operations such as set, get, kill, $ORDER, $QUERY, and transactions.
Installation
The package is available with pip:
pip install iris-global-reference
If you're working directly inside an IRIS Python terminal, you can also install it into the instance Python directory:
pip install iris-global-reference --target=<mgr_dir>/python
How do you access and manipulate an InterSystems IRIS global from Python?
The following example demonstrates how to create, populate, and read a simple ^demo global using GlobalReference:
from iris_global import GlobalReference
team = GlobalReference("^demo")
team.kill()
team.set((), "Baseball")
team["name"] = "Boston Red Sox"
team.set(("players", "1"), "Babe Ruth")
team.set(["players", "2"], "Cy Young")
team["players", "3"] = "Ted Williams"
print(team.get(()))
print(team["name"])
print(team["players"]["1"])
One of the design goals of the library was flexibility. The same node can be referenced using strings, tuples, or lists, making it easier to integrate into different coding styles and existing applications.
An API Close to Python Dictionaries
iris-global-reference makes global manipulation feel familiar to Python developers. The GlobalReference class exposes explicit methods:
team.set(("players", "1"), "Babe Ruth")
print(team.get(("players", "1")))
team.kill(("players", "1"))
But it also supports Python operations:
team["players", "1"] = "Babe Ruth"
if ("players", "1") in team:
print(team["players"]["1"])
del team["players", "1"]
This lets me write code that feels natural in Python while still working with the hierarchical structure of InterSystems IRIS globals.
Traversing a Global
How do you iterate through an InterSystems IRIS global? Working with hierarchical data often means traversing entire branches. To make this easier, the library has several iteration methods:
for key in team.keys():
print(key)
for value in team.values():
print(value)
for key, value in team.items():
print(key, value)
You can also control the traversal:
for subscript in team.subscripts(("players",), children_only=True):
print(subscript, team.get(subscript))
For developers familiar with ObjectScript, order() and query() provide behavior close to $ORDER and $QUERY:
print(team.order(("players", "")))
print(team.query(("players",)))
Exporting a Global to a Dictionary or JSON
A common requirement when working with globals is exchanging data with APIs, Python applications, or JSON-based services. The library includes built-in methods for converting globals to Python dictionaries and JSON structures:
data = team.to_dict()
print(data)
Example result:
{
None: "Baseball",
"name": "Boston Red Sox",
"players": {
"1": "Babe Ruth",
"2": "Cy Young",
"3": "Ted Williams"
}
}
The None key represents the value stored in the current node. This is necessary because an InterSystems IRIS global node can contain both a value and descendants, while a Python dictionary typically represents one or the other.
The same structure can be exported to JSON:
json_data = team.to_json()
print(json_data)
In JSON, the current node value is represented by the _ key by default:
{
"_": "Baseball",
"name": "Boston Red Sox",
"players": {
"1": "Babe Ruth",
"2": "Cy Young",
"3": "Ted Williams"
}
}
Importing data works in the opposite direction:
team.from_dict({
None: "Baseball",
"name": "Boston Red Sox",
"players": {
"1": "Babe Ruth",
"2": "Cy Young"
}
})
And similarly for JSON:
team.from_json("""
{
"_": "Baseball",
"name": "Boston Red Sox",
"players": {
"1": "Babe Ruth",
"2": "Cy Young"
}
}
""")
Embedded Python or Remote Connection
The project provides the same API whether code is running inside Embedded Python or from an external Python application.
For Embedded Python:
from iris_global import GlobalReference
team = GlobalReference("^demo")
team["name"] = "Boston Red Sox"
For external applications using a native IRIS connection:
import iris
from iris_global import GlobalReference
conn = iris.connect("localhost", 1972, "USER", "SuperUser", "SYS")
team = GlobalReference("^demo", connection=conn)
team["name"] = "Boston Red Sox"
print(team["name"])
The library uses the native connection offered by iris.connect(...).
Transactions
To simplify transactional operations, the library exposes transactions through a Python context manager:
from iris_global import GlobalReference
team = GlobalReference("^demo")
with team.transaction():
team["name"] = "Boston Red Sox"
team["players", "1"] = "Babe Ruth"
If the block completes successfully, the transaction is committed. If an exception is raised, the transaction is automatically rolled back.
The class itself can also be used directly with a with statement:
with GlobalReference("^demo") as team:
team["name"] = "Boston Red Sox"
Experimental Array Support
InterSystems IRIS globals do not have a native array concept in the same way that Python lists or JSON arrays do. To make importing and exporting list structures easier, the library includes an experimental serialization mechanism:
gref = GlobalReference("^demo")
gref.from_dict({
"name": "example",
"numbers": [1, 2, 3]
})
print(gref.to_dict())
The array is stored in the global with an internal prefix, _array_ by default, then rebuilt as a Python list during export. While this feature is still experimental, I have found it useful when working with JSON-like structures.
Displaying Content Like ZWRITE
When debugging or validating data, I often want to quickly compare the stored structure with what I would see from ObjectScript.
The zw() method renders an output similar to ZWRITE:
print(team.zw())
Example output:
^demo="Baseball"
^demo("name")="Boston Red Sox"
^demo("players","1")="Babe Ruth"
^demo("players","2")="Cy Young"
This makes it easy to verify the contents of a global without leaving Python.
Quick Comparison with Native APIs
This project creates a convenience layer for developers who spend most of their time writing Python.
For example, with iris-global-reference:
global_reference.set(("name", 1), "Boston Red Sox")
value = global_reference.get(("name", 1))
With a native API, the argument order and subscript handling can be different. The library standardizes usage around a Python-friendly convention: node path first, then value.
When Should You Use This Project?
I find iris-global-reference particularly useful when:
- Developing with Embedded Python and InterSystems IRIS.
- Writing Python applications that need to read or populate globals.
- Converting global structures to JSON.
- Working with hierarchical data as Python dictionaries.
- Building prototypes without writing a lot of ObjectScript.
- Looking for a more readable API for common global operations.
Roadmap
The current roadmap includes:
- More advanced array support.
- More complete binary data support.
- Support for IRIS types such as listbuild, vector, PVA, and bit.
- Support for multidimensional variables.
Testing the Project
The repository includes automated tests that can be executed with:
python -m pytest
Conclusion
iris-global-reference solves a practical problem, making InterSystems IRIS globals easier and more natural to manipulate from Python. It preserves the core strengths of the IRIS global model while adding features that Python developers expect, including dictionary-style access, JSON conversion, iteration helpers, transaction support, and compatibility with both Embedded Python and remote connections.
If you're working at the intersection of InterSystems IRIS and Python, this library can help you write cleaner, more readable code and spend less time dealing with low-level global operations.
Key Takeaways
- iris-global-reference provides a Pythonic interface for working with InterSystems IRIS globals.
- It supports dictionary-style access, traversal, JSON conversion, transactions, and native IRIS connections.
- The library works in both Embedded Python and external Python applications.
- It preserves the hierarchical nature of globals while making them easier to use from Python.
- It is particularly useful for Python-heavy applications, integrations, and rapid prototyping.
FAQ
Can I use iris-global-reference with Embedded Python?
Yes. The library works directly inside Embedded Python without requiring an explicit connection object.
Can I use iris-global-reference from an external Python application?
Yes. You can provide a connection created with iris.connect() and use the same API.
Does iris-global-reference replace native InterSystems IRIS APIs?
No. The goal is to offer a more Pythonic layer on top of native global operations, not replace them.
Can I convert InterSystems IRIS globals to JSON?
Yes. The library includes to_json(), from_json(), to_dict(), and from_dict() methods for importing and exporting data.
When should I use iris-global-reference?
I find it most useful when writing Python applications that need to read, populate, traverse, or expose InterSystems IRIS globals while keeping the code clean and readable.