Separate stdout data from stderr diagnostics in a CLI
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.