Python on z/OS is increasingly being used not to replace existing systems, but to simplify how teams work with them.
This article explores where to start using Python on z/OS, beginning with a simple, familiar example and expanding outward into common patterns across operations, data, and integration.
The ABEND Report
The problem
The first thing I checked that morning was the ABEND report. Not because anything had gone wrong, just out of habit. Something runs overnight, something always does, and by the time you’re back, the system has already written its story down. You just have to go find it.
The shift with Python
Except this time, I didn’t go looking. A small Python script had already scanned the output, pulled out what mattered, and left a short summary waiting.
The result
A few lines told me what failed, where, and gave enough context to act. The log stayed where it was. Python worked on it there.
That ABEND report is just one example. The system produces artifacts like this everywhere: logs, outputs, traces, data written down in different forms, across different workflows, and most days, we go to them. What’s starting to change is simpler: not that these artifacts exist, but how you interact with them. We’ll come back to this pattern in code shortly.
Understanding System Artifacts
That ABEND report isn’t special. It’s one of many ways the system leaves a trail behind as it runs: logs, job outputs, traces, datasets. Each captures part of what happened.
Step back, and a pattern appears. There’s text to interpret, numbers to analyze, flows to orchestrate, work to trigger, data to process in place, and checks to run before the next step. Most teams already work in these spaces every day. What’s changing is not that they exist, but how you interact with them.
From Outputs to Action
All those areas have something in common: the data is already on the system where the work began. For a long time, doing anything useful meant pulling it out: exporting, copying, or moving it somewhere else first.
What’s changed is that you can now bring the work to the data instead. The ABEND report stays where it is. The script acts in place. Once you see that, these system artifacts stop being just outputs to inspect. They become places you can act. Instead of opening SDSF and scanning, the system flags what matters.
Where Python Fits in Practice
Python on z/OS is no longer a curiosity, it’s a practical tool showing up in real workloads, often in places where traditional languages are either too rigid or too heavy.
Key Use Cases
Integration & Glue
What it does
Connects DB2, job output, APIs, and existing services into simple, readable workflows.
When to use
When work spans multiple systems, tools, or formats and requires coordination.
Why it matters
Reduces friction. Replaces multi-step manual or scripted workflows with a single, understandable layer.
This is Python’s home turf. It excels at stitching together DB2 queries, job output, REST APIs, and existing COBOL or Java services without ceremony. Need to expose a z/OS transaction as a REST endpoint, enrich with DB2 data, generate modern reports, and respond? That’s a few libraries and a clear script, not a framework migration. Python lowers the friction of using your platform.
If your day involves running a query, calling an API, copying results, and formatting output across multiple tools, Python can collapse that into one script.
Data Processing & Transformation
What it does
Parses, reshapes, and enriches data already on the system.
When to use
When extracting, normalizing, or preparing data for downstream analytics or AI.
Why it matters
Improves adaptability without replacing existing batch processes.
z/OS is where high-value data lives; Python is a powerful vehicle for shaping it. Whether you’re parsing logs, normalizing records, or feeding downstream analytics and AI, Python handles transformation pipelines with clarity and speed of iteration. It’s not about replacing batch, it’s about making batch more adaptable, testable, and composable.
If you routinely extract data, reshape it, and pass it downstream, this is your entry point.
DevOps / Automation
What it does
Automates job flows, environment checks, and operational processes.
When to use
When reruns, orchestration, or coordination logic spans multiple scripts or tools.
Why it matters
Makes operational logic visible, testable, and easier to evolve.
Build, deploy, operate: Python comfortably automates all three. From JCL generation or replacement to z/OSMF workflows, from environment auditing and validation to operational scripts, Python can bring consistency across teams. The payoff is mundane but meaningful: fewer brittle scripts, more readable and modern automation, and faster recovery when things go sideways.
If you find yourself managing job flows, reruns, or environment checks across multiple scripts and tools, this is a natural fit.
AI/ML Adjacency
What it does
Connects models and scoring systems back to system-of-record data.
When to use
When decisions or predictions need to be applied close to core data.
Why it matters
Reduces latency and avoids unnecessary data movement.
The models may train elsewhere, but z/OS is where decisions often land. Python bridges that gap, handling preprocessing, lightweight inference, or model-serving endpoints close to system-of-record data. The result: less data movement, tighter latency, and a cleaner path from insight to action.
If your workflows depend on external scoring, predictions, or decision APIs, this is where Python connects them back to system-of-record data.
Bottom line: Python doesn’t compete with z/OS strengths, it amplifies them, acting as a pragmatic layer for integration, transformation, and automation right where enterprise work happens.
Examples In Code
Abstract value is nice. Working code is better. Here are three patterns showing Python earning its keep on z/OS. These build from simplest to more involved: observing -> acting -> shaping data.
1) The ABEND Report
Recall the ABEND example from earlier. The point was not the report itself, but the pattern: Python scanning existing system output in place and surfacing what matters. Here’s what that looks like in code.
Example: Scanning JES output with ZOAU
from zoautil_py import jobs
def find_abends():
alerts = []
# job_owner filters by owner; see note on '*' wildcard
for job in jobs.fetch_multiple(job_owner="*"):
# Keep only terminal jobs (skip active "AC" and unknown None)
if job.status not in ("CC", "ABEND", "CANCELED"):
continue
try:
output = jobs.read_output(job.job_id)
except Exception:
continue
if "ABEND" in output or "S0C" in output:
alerts.append({
"job": job.name,
"id": job.job_id,
"class": job.job_class,
})
return alerts
if __name__ == "__main__":
for a in find_abends():
print(f"{a['job']} ({a['id']}) flagged potential ABEND")
A few lines. No new infrastructure. No movement of data. Just a shift in posture: from hunting through output to letting signal surface itself.
2) Automating batch workflows and ops tasks
Python excels at automation, especially when operational logic exists across jobs, schedules, and rerun conditions rather than in one visible place. A few lines of Python can make that flow explicit.
Example: orchestrating batch with ZOAU
from zoautil_py import jobs
import time
job = jobs.submit("USER.JCL(DAILYRUN)")
jobid = job.job_id
while True:
j = jobs.fetch(jobid)
if j.status in ("CC", "ABEND", "CANCELED"): # terminal states
break
time.sleep(5)
if j.return_code != "0000":
# simple retry or alternate path
retry = jobs.submit("USER.JCL(RETRY)")
print(f"Retry submitted: {retry.job_id}")
A small script. No new system. Just the logic, finally sitting where it can be seen and changed.
3) Data pipeline with DB2, files, and services
The data was never the problem. It was already there: structured, trusted, complete. In DB2 tables, datasets, and job flows.
What was missing was context: a join, a lookup, just enough meaning to make the data usable.
So, you add a thin layer. Not a platform. Not a product. Just a script that reads, shapes, and enriches data where it already lives. That shortens the distance between stored, understood, and acted upon.
Example: DB2 data + lightweight enrichment
import ibm_db
import requests
# Connection details come from DSNAOINI/odbc.ini (z/OS local subsystem)
conn = ibm_db.connect("", "", "")
stmt = ibm_db.exec_immediate(
conn,
"SELECT ID, AMT FROM TXN WHERE PROC_DT = CURRENT DATE"
)
row = ibm_db.fetch_assoc(stmt)
while row:
try:
resp = requests.get(f"https://risk.example.com/api/{row['ID']}", timeout=5)
resp.raise_for_status()
risk = resp.json()["score"]
if risk > 80:
print(f"High risk txn: {row['ID']} amount={row['AMT']} score={risk}")
except (requests.RequestException, KeyError, ValueError) as e:
print(f"Skipping {row['ID']}: {e}")
row = ibm_db.fetch_assoc(stmt)
ibm_db.close(conn)
Nothing moved. Nothing replaced. A thin layer that turns data into signal, right where it already is.
So how does this become real for you?
Where Do I Start?
If you’re new to Python on z/OS, don’t start everywhere. Start where your day already has friction:
If you spend time reading logs or job output
→ Start with scanning and summarizing (like the ABEND example)
If you manage batch flows or reruns
→ Start with orchestration scripts
If you move data between systems or reshape it
→ Start with small data pipelines
If you integrate across APIs, DB2, and services
→ Start with glue scripts
The right first step is not new capability. It’s removing one repetitive task from your day. New use cases will inevitably occur to you as you gain practical experience.
The Real Shift
It’s worth being clear about what this is not. This is not a call to replace COBOL, PL/I, or Java, and it’s not a blanket modernization program.
Python on z/OS is about reducing the friction of using what already works.
The core of z/OS stays exactly what it is. Stable, performant, and trusted. What changes is how you move around it.
The map we started with still holds: integration, data, automation, and adjacency to AI. Python doesn’t sit in one of those boxes; it runs across them. The same approach that starts with scanning ABENDs can extend into batch orchestration or lightweight data pipelines. A one-off utility quietly turns into something a team depends on, not by design, but through use.
That’s the shift: small pieces, written close to the work, that accumulate into capability. Time to value is quick and it compounds.
Once you have that layer, once the system can be seen and shaped this way, something new becomes possible. Not immediately, and not everywhere, but naturally: those same entry points start to look like places where the python ecosystem, higher-level tooling, even agents, can plug in.
That’s fuel for a future article. For now, the change is simpler.
Python doesn’t replace the system, it changes how you move through it.
And once that shift happens, the system stops being something you inspect, and starts becoming something that works with you.
#Python