Registry / devops / sh
library2.4.0pypypi✓ verified 24d ago

sh is a full-fledged subprocess replacement for Python (3.8 - 3.12) that allows you to call any program on your system as if it were a function. It dynamically resolves programs from your `$PATH`, similar to Bash, and wraps them in callable Python functions, offering an intuitive way to write shell scripts in Python. The current version is 2.2.2, and it maintains an active release cadence with regular bug fixes and minor feature additions.

pip install sh
INSTALL
IMPORT
SIG · SH
S
sh
devopspythonv2.4.0
Install
1.7s avg
Import
287ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v2.4.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.103.95 runs
installs and imports cleanly · install 0.0s · import 0.310s · 18.1MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 1.7s · import 0.264s · 19MB
16MB installed
● package 16MB
Code
Verified usage

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

sh
import sh
Imports the main 'sh' object, from which system commands are accessed as attributes (e.g., sh.ls).
Command
from sh import Command
Useful for explicitly calling commands not in PATH or with special characters, e.g., `cmd = Command('/usr/bin/ffmpeg')`.
ErrorReturnCode
from sh import ErrorReturnCode_127
Specific error codes (e.g., ErrorReturnCode_1, ErrorReturnCode_127) are raised when a command exits with a non-zero status. Catch `sh.ErrorReturnCode` for a general handler.
bash
from sh.contrib import bash
Introduced in 2.1.0 for improved Bash integration.

This quickstart demonstrates basic command execution, passing arguments, capturing output, handling non-zero exit codes, and piping commands. Replace `ls` and `python` with commands available on your system.

import sh import os # Get the current user user = os.environ.get('USER', 'unknown_user') print(f"Hello, {user}!") # Run a simple command and capture output output = sh.ls('-l', '/tmp') print(f"\nls -l /tmp:\n{output}") # Run a command with arguments version_info = sh.python('-V') print(f"\nPython version:\n{version_info}") # Handle a non-zero exit code try: sh.false() except sh.ErrorReturnCode_1 as e: print(f"\nCaught expected error: {e.full_cmd}, Exit Code: {e.exit_code}") # Pipe commands (similar to shell) piped_output = sh.wc('-l', _in=sh.ls('-1')) print(f"\nNumber of files in current directory: {piped_output.strip()}")
Debug
Known issues
breakingThe `sh` library is designed exclusively for Unix-like operating systems (Linux, macOS, BSDs). It relies on various Unix system calls and does not support Windows environments.
fix
Use `subprocess` module or alternative libraries for cross-platform compatibility, or ensure deployment on Unix-like systems only.
affects: All versions
breakingUpgrading from `sh` 1.x to 2.x involves significant breaking changes. Users are strongly advised to consult the `MIGRATION.md` file in the project's repository or PyPI page before upgrading.
fix
Review `MIGRATION.md` and adapt code as necessary to align with the 2.x API.
affects: 1.x to 2.x migration
gotchaWhen an executed command exits with a non-zero status code, `sh` raises an `sh.ErrorReturnCode_X` exception (where X is the exit code), rather than silently failing. This behavior must be explicitly handled with `try...except` blocks.
fix
Wrap command calls that might return non-zero exit codes in `try...except sh.ErrorReturnCode` blocks to handle errors gracefully.
affects: All versions
gotchaPrior to version 2.2.2, using `async` commands in combination with `_return_cmd=True` could lead to unexpected behavior. Specifically, `await` on such a command might return `str(self)` instead of a `RunningCommand` object, and earlier versions (pre-2.2.1) had bugs where async commands with `return_cmd` did not raise exceptions correctly.
fix
Upgrade to `sh` 2.2.2 or later to ensure correct asynchronous behavior and error handling for commands using `_return_cmd=True`.
affects: <2.2.2
gotchaWhile `sh` provides a Pythonic wrapper, it directly executes underlying shell commands. This means many common shell footguns (e.g., issues with improper quoting, globbing, or special characters in filenames) can still affect your scripts.
fix
Be mindful of shell scripting best practices, especially concerning argument quoting and validation. Leverage `sh`'s list-based argument passing where possible, as it generally handles quoting automatically.
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'sh'
The 'sh' library is not installed in the Python environment being used.
fix
Install the library using pip: `pip install sh`
sh.CommandNotFound: <command_name> not found
The external command specified (e.g., 'git', 'ls') is not found in the system's PATH environment variable.
fix
Ensure the command is installed and its directory is included in your system's PATH, or provide the full path to the executable.
sh.ErrorReturnCode_N: <command_name> returned non-zero exit status N
The executed external command exited with a non-zero status code, signaling that it failed or encountered an error.
fix
Handle the exception by wrapping the call in a `try...except sh.ErrorReturnCode` block, inspect `e.stderr` or `e.stdout` for details, or ensure the command's arguments are correct.
sh.TimeoutException: Timeout while running <command_name>
The external command took longer to execute than the specified `_timeout` duration.
fix
Increase the `_timeout` parameter when calling the `sh` command, or investigate why the command is taking too long to execute.
AttributeError: '_ShProc' object has no attribute 'splitlines'
The return value of an `sh` command is a `_ShProc` object, not a plain string, and string methods like `splitlines()` must be called after explicit conversion to `str` or `bytes`.
fix
Convert the `_ShProc` object to a string using `str()` before calling string methods, for example: `str(sh.ls()).splitlines()` or `sh.ls().stdout.decode().splitlines()`.
Upgrade
Version history
2.4.0latest on PyPI · released Jul 25, 2026
Audit
Dependencies
pythonrequiredRequired Python version range
Agent activity
27 hits · last 30 days
node
24
Resources
sh — pip install sh · libregistry