Batu Lab NotesPractical developer guides

Separate stdout data from stderr diagnostics in a CLI

By Batu · English technical notes

Also published in our Blogger archive.

Quick answer

sys.stdout and sys.stderr are separate text streams, so a command can reserve stdout for data and stderr for human diagnostics.

Example

The example emits compact JSON through print’s default stdout and a synthetic-input note with file=sys.stderr. The assertion fixes the JSON serialization, while the two print calls make the stream assignment explicit.

import json, sys

def report(ok):
    print(json.dumps({'ok': ok}, separators=(',', ':')))
    print('checked synthetic input', file=sys.stderr)
report(True)
assert json.dumps({'ok': True}, separators=(',', ':')) == '{"ok":true}'

Expected stdout:

{"ok":true}

Reading the result

A consumer that needs to verify the stream boundary should run the script in a subprocess and capture both streams. This short example demonstrates the writer side only.

Keep progress bars, warnings, and retry notices on stderr too. Once stdout is promised as JSON, even a friendly prefix can make a downstream parser reject the entire response.

The JSON is compact to make an exact stdout contract easy to inspect. The stderr line is deliberately non-JSON, which demonstrates why a consumer must read only stdout as data.

Sources

- Python sys module documentation

Prepared with AI assistance. The example uses synthetic data; its stated limits apply.