Python subprocess replacement that allows calling system commands as Python functions
—
Core functionality for executing system commands with comprehensive process control, argument handling, and execution modes. Commands can be executed in foreground, background, or interactive modes with extensive configuration options.
Execute system commands by calling Command objects as functions, with arguments passed as function parameters.
def __call__(self, *args, **kwargs):
"""
Execute the command with given arguments.
Parameters:
- *args: Command arguments (strings, numbers, or Path objects)
- **kwargs: Execution options and special parameters
Returns:
str: Command output (stdout) for foreground execution
RunningCommand: Process object for background execution (_bg=True)
"""Usage examples:
import sh
# Basic command execution
output = sh.ls("-la", "/tmp")
print(output)
# Pass arguments as separate parameters
sh.git("add", ".")
sh.git("commit", "-m", "Initial commit")
# Mix different argument types
from pathlib import Path
sh.cp("file.txt", Path("/backup/"))Create pre-configured Command objects with default arguments and options, useful for commands that need consistent parameters.
def bake(self, *args, **kwargs):
"""
Create a new Command with pre-configured arguments.
Parameters:
- *args: Default arguments to include in all executions
- **kwargs: Default execution options
Returns:
Command: New Command object with baked-in arguments
"""Usage examples:
import sh
# Create pre-configured commands
ls_long = sh.ls.bake("-la")
git_log = sh.git.bake("log", "--oneline")
# Use pre-configured commands
output1 = ls_long("/tmp") # Equivalent to ls("-la", "/tmp")
output2 = ls_long("/home") # Equivalent to ls("-la", "/home")
commits = git_log("-10") # Equivalent to git("log", "--oneline", "-10")
# Bake with execution options
docker_exec = sh.docker.bake("exec", _tty=True, _env={"TERM": "xterm"})
result = docker_exec("container_name", "bash")Execute commands asynchronously in the background, allowing the Python script to continue while the command runs.
def __call__(self, *args, _bg=True, **kwargs):
"""
Execute command in background.
Parameters:
- _bg: bool = True to run in background
Returns:
RunningCommand: Process object for monitoring and control
"""Usage examples:
import sh
import time
# Start command in background
proc = sh.sleep(10, _bg=True)
print("Command started, continuing...")
# Do other work while command runs
time.sleep(2)
print(f"Command still running: {proc.is_alive()}")
# Wait for completion
proc.wait()
print("Command completed")
# Multiple background processes
procs = []
for i in range(5):
proc = sh.ping("-c", "5", f"host{i}.example.com", _bg=True)
procs.append(proc)
# Wait for all to complete
for proc in procs:
proc.wait()
print(f"Ping completed with exit code: {proc.exit_code}")Execute commands with TTY allocation for interactive programs that require terminal input/output.
def __call__(self, *args, _tty=True, **kwargs):
"""
Execute command with TTY allocation.
Parameters:
- _tty: bool = True to allocate a TTY
Returns:
str: Command output
"""Usage examples:
import sh
# Interactive commands requiring TTY
sh.vi("file.txt", _tty=True)
sh.less("/var/log/syslog", _tty=True)
# Docker containers with interactive shell
sh.docker("run", "-it", "ubuntu", "bash", _tty=True)
# SSH sessions
sh.ssh("user@server", _tty=True)Check for command availability and get command information before execution.
class Command:
def __str__(self) -> str:
"""String representation showing executable path and baked arguments."""
def __repr__(self) -> str:
"""Formal string representation of the Command object."""Usage examples:
import sh
# Check if command exists
try:
git_cmd = sh.Command("git")
print(f"Git command: {str(git_cmd)}")
except sh.CommandNotFound:
print("Git not installed")
# Dynamic command discovery
commands_to_check = ["docker", "kubectl", "helm"]
available = []
for cmd_name in commands_to_check:
try:
cmd = sh.Command(cmd_name)
available.append(cmd_name)
print(f"{cmd_name}: {str(cmd)}")
except sh.CommandNotFound:
print(f"{cmd_name}: not found")Various execution options can be specified as keyword arguments to control command behavior.
def __call__(self, *args,
_bg=False, # Background execution
_tty=False, # TTY allocation
_cwd=None, # Working directory
_env=None, # Environment variables
_timeout=None, # Execution timeout
_ok_code=None, # Expected exit codes
**kwargs):
"""Execute command with options."""Usage examples:
import sh
import os
# Change working directory
output = sh.ls(_cwd="/tmp")
# Set environment variables
result = sh.env(_env={"MY_VAR": "value", "PATH": os.environ["PATH"]})
# Set timeout
try:
sh.sleep(60, _timeout=10) # Will timeout after 10 seconds
except sh.TimeoutException:
print("Command timed out")
# Accept different exit codes as success
try:
sh.grep("pattern", "file.txt", _ok_code=[0, 1]) # 0=found, 1=not found
except sh.ErrorReturnCode:
print("Unexpected error occurred")Install with Tessl CLI
npx tessl i tessl/pypi-sh