2025, Nov 15 07:00
Fixing bracket and encoding errors in Python on z/OS caused by 3270 emulator ISPF Edit code page and keyboard mapping
Troubleshoot Python on z/OS when brackets become glyphs in ISPF Edit. Fix UTF-8/Syntax errors by correcting 3270 emulator code page and keyboard mapping.
Editing Python on z/OS can be unexpectedly tricky when a 3270 emulator and ISPF Edit are in the loop. A common symptom is that square brackets suddenly appear as triangular glyphs in the editor. The file then fails at runtime with encoding or syntax errors, even though the code itself is valid Python. The root of this behavior lies not in Python, but in terminal code pages and keyboard mapping.
Minimal example that triggers the issue
The following snippet reads a dataset member in USS and prints the first four characters of each line. The logic is straightforward; trouble starts the moment the brackets are entered in the ISPF editor through a misconfigured emulator.
from zoautil_py import datasets as ds_api
data_ref = "'CICS.H39808.PROCLIB(S55CTL)'"
text_blob = ds_api.read(data_ref)
row_list = text_blob.split('\n')
for rec in row_list:
print(rec[0:4])
Printing the entire line instead of slicing often works in this scenario. As soon as slicing with [0:4] is reintroduced, the brackets that looked normal morph into other characters on save, and Python reports errors such as a UnicodeDecodeError for UTF-8, or a SyntaxError complaining about “Non-UTF-8 code … but no encoding declared.” Attempts to flip encodings with iconv or to add a source encoding declaration like cp1047 can then lead to new errors or “illegal character sequence” messages.
What’s really going on
The critical piece is the environment used to create and edit the file: a 3270 emulator driving TSO/ISPF Option 3.17 to edit USS content. The emulator’s code page and keyboard mapping govern which EBCDIC bytes are written when you press [ and ]. If the mapping is off, the editor will store different characters altogether. Python then reads those bytes and either fails to decode them as UTF-8 or treats them as invalid syntax.
There is a simple way to confirm the mapping: enable Hex display in ISPF Edit while viewing the file and inspect the bytes for the bracket characters. For the correct mapping, you should see x’ad’ for [ and x’bd’ for ]. If you see different values, the emulator is not sending the expected codes.
This also explains why transcoding after the fact does not help. If the wrong bytes were introduced at input time, converting encodings only shuffles incorrect bytes between character sets. Likewise, adding a coding cookie such as cp1047 will not fix characters that were never brackets to begin with, and may surface new decoding failures. In contrast, creating the file outside ISPF—for example, editing locally in Notepad++ and transferring to USS, or working directly over SSH—avoids the 3270 path and the associated keyboard/code page pitfalls.
How to fix it
Start by correcting the 3270 emulator configuration. Verify the emulator code page and ensure the keyboard mapping for [ and ] uses the expected codes. After adjusting, open the file in ISPF Edit, turn on Hex, and confirm that the brackets are stored as x’ad’ and x’bd’. Once those bytes are right, the source will save correctly, and Python will stop tripping over decoding and syntax errors associated with the bracket characters.
If you are creating and editing files specifically for USS, consider working directly in a shell session rather than through ISPF Edit. This avoids 3270 code page peculiarities entirely. In the discussion that led to the fix, files created outside ISPF (for example, with Notepad++ and then transferred to USS) behaved as expected, while files edited under ISPF with a misconfigured emulator did not.
Working code after fixing the environment
Once your emulator and keyboard mapping are correct, no changes to the Python logic are needed. The same program works as intended when brackets are recorded with the proper bytes.
from zoautil_py import datasets as ds_api
mbr_ref = "'CICS.H39808.PROCLIB(S55CTL)'"
content = ds_api.read(mbr_ref)
records = content.split('\n')
for row in records:
print(row[0:4])
Why this matters
On z/OS, correctness is not only about code; it’s also about the path your characters take from keyboard to file. A misaligned 3270 setup can silently rewrite characters into different EBCDIC codes, making otherwise valid Python un-runnable. Recognizing the symptoms—brackets turning into other glyphs in ISPF, persistent UnicodeDecodeError or SyntaxError about non‑UTF‑8 bytes—and knowing to check the emulator’s code page and keyboard mapping saves hours of trial-and-error with iconv or encoding cookies.
Takeaways
If square brackets and other punctuation mysteriously change in ISPF Edit and Python starts raising encoding or syntax errors, look at the emulator first. Confirm the 3270 code page and keyboard mapping, and use Hex mode in the editor to verify that [ and ] are x’ad’ and x’bd’. When possible, edit USS files over SSH or prepare them off-platform and transfer in; this sidesteps the 3270 code page and keyboard mapping concerns entirely. With the environment set up correctly, your Python source will store the intended characters, and the original logic will run without further changes.