Registry / devops / runs
library1.3.0pypypi✓ verified 29d ago

Runs is a Python library (version 1.3.0) that enhances the standard `subprocess` module by providing improved functions to execute blocks of text as sequences of shell commands. It adds features like multi-command execution, line continuations, comment handling, optional logging, error handling, lazy evaluation, and defaults to UTF-8 encoding. It offers more robust handling for scenarios that often trip up the native `subprocess` functions.

pip install runs
INSTALL
IMPORT
SIG · RUNS
R
runs
devopspythonv1.3.0
Install
1.6s avg
Import
25ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.9–3.13
musl
3.9–3.13
Install & Compatibility
Where this runs
tested against v1.3.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.028s · 17.8MB
glibc
py 3.10–3.95 runs
installs and imports cleanly · install 1.6s · import 0.022s · 18MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

run
✓ from runs import run
Used for executing commands and waiting for completion, returning a list of results.
call
✓ from runs import call
Equivalent to subprocess.call() but for multiple commands/text blocks.
check_call
✓ from runs import check_call
Similar to subprocess.check_call(), raises CalledProcessError on non-zero exit codes.
check_output
✓ from runs import check_output
Similar to subprocess.check_output(), captures output and raises CalledProcessError on failure.

This example demonstrates how to use `runs.run()` to execute a multi-line block of commands and capture their output. It also shows how to enable echoing commands and handle exceptions from failing subprocesses. The library provides a more convenient interface for common shell interactions than the raw `subprocess` module.

from runs import run # Run a block of text as multiple commands output = run(''' echo "Hello from Runs!" ls -l ''') for line in output: print(line) # Run with error handling and echo try: result = run('false; echo ok', on_exception=False, echo=True) except Exception as e: print(f"Caught expected error: {e}") # Get stdout of a single command stdout_list = run('echo "Single command output"') print(stdout_list[0])
Debug
Known issues
gotchaBy default, the `runs` library splits input text into commands by newlines. Ensure that multi-line commands intended as a single unit use line continuations (e.g., `\`) as expected by your shell, or pass commands as a list of strings.
fix
Use explicit line continuations for multi-line shell commands within a single text block, or pass commands as a list of strings if precise command separation is critical, e.g., `runs.run(['command arg1 arg2', 'another_command'])`.
affects: All versions
gotchaWhile `runs` aims to improve `subprocess` error handling, raw shell commands executed with `shell=True` (which `runs` implies when passing a single string block) are susceptible to shell injection if untrusted input is included. Always sanitize or escape user-provided data.
fix
Avoid constructing command strings with unsanitized user input. If user input must be part of a command, pass the command and its arguments as a list of strings (where each element is an argument) rather than a single string, to bypass shell interpretation. Alternatively, use `shlex.quote()` to properly escape individual arguments.
affects: All versions
gotchaThe `runs` library processes commands sequentially. For long-running or concurrent tasks, using `runs` might block your main program. It does not inherently provide asynchronous execution or process management capabilities beyond waiting for completion.
fix
For asynchronous or parallel execution, consider directly using `subprocess.Popen` or dedicated async/parallel processing libraries like `asyncio.create_subprocess_exec` or `multiprocessing`.
affects: All versions
breakingThe library's functions (e.g., `run()`, `check_output()`) return a list of strings, one for each command executed in the input block. This differs from `subprocess.run()` which returns a single `CompletedProcess` object.
fix
Adjust your code to iterate over the returned list if you expect multiple outputs, or access `result[0]` if only the first command's output is relevant. Remember that each element in the list is the `stdout` of a command, not a `CompletedProcess` object.
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'runs'
The 'runs' library has not been installed in your current Python environment.
fix
Install the library using pip: `pip install runs`
TypeError: expected str, bytes or os.PathLike object, not list
The 'runs.execute()' function expects a single string containing the shell command(s), not a list of arguments, when 'shell=True' (which is the default).
fix
Pass the command as a single string: `runs.execute("ls -l")`
runs.CalledProcessError: Command 'nonexistent_command' returned non-zero exit status 127.
The shell command executed by 'runs.execute()' returned a non-zero exit status, indicating an error during its execution (e.g., command not found, incorrect arguments, permission denied).
fix
Verify that the shell command is correct, exists in the system's PATH, and has the necessary permissions. You can also disable checking with `check=False` if a non-zero exit status is expected for your use case.
AttributeError: 'generator' object has no attribute 'stdout'
When using 'runs.lazy_execute()', it returns a generator object, which needs to be iterated over to yield the 'CompletedProcess' objects that contain attributes like 'stdout'.
fix
Iterate over the generator to access the results: `for result in runs.lazy_execute("echo hello"): print(result.stdout)`
Upgrade
Version history
1.3.0latest on PyPI · released Feb 3, 2026
Audit
Dependencies

No dependency data recorded yet.

Agent activity
22 hits · last 30 days
node
20
OpenAI (training)
1
Resources
runs — pip install runs · libregistry