Alternatives
A quick look at other ways to run external commands in Python, and when they might fit better than comrun.
Python standard library
subprocess.run/subprocess.Popen: battle-tested and built in, but requires boilerplate. You manage streaming, decoding, and error handling yourself. This friction is what inspired the creation of comrun.asyncio.create_subprocess_exec: async-friendly subprocesses. You handle reading/writing streams and timeouts.
Use these when you want zero dependencies and are fine wiring up I/O, timeouts, and logging yourself.
Higher-level libraries
- Invoke / Fabric: task runners with decorators, remote execution, and SSH. Good for deployment scripts; heavier footprint than comrun.
- plumbum: shell-like DSL with pipelines and path abstractions; nice for Unix-like scripting, more opinionated than comrun.
- sh-style wrappers (e.g.,
sh,delegator.py): call executables as functions (git.status()), oftenshell=True; convenient, but can hide quoting concerns.
Choose these when you want richer task abstractions or DSL-like command composition.
When to choose comrun?
You want a small, synchronous runner with:
- Live output streaming (via Rich) and captured stdout/stderr/combined output.
- Structured results and simple success/failure helpers.
- Hooks for logging/metrics without adopting a heavier task runner.