or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/pypi-sh

Python subprocess replacement that allows calling system commands as Python functions

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/sh@2.2.x

To install, run

npx @tessl/cli install tessl/pypi-sh@2.2.0

0

# sh

1

2

A comprehensive Python subprocess replacement that allows calling any system command as if it were a Python function. The `sh` library provides a more Pythonic interface to shell commands with advanced process management, piping, background execution, and real-time output streaming for Unix-like systems.

3

4

## Package Information

5

6

- **Package Name**: sh

7

- **Language**: Python

8

- **Installation**: `pip install sh`

9

- **Supported Platforms**: Linux, macOS, BSD (Unix-like systems only)

10

- **Python Versions**: 3.8-3.12, PyPy

11

12

## Core Imports

13

14

```python

15

import sh

16

```

17

18

For specific commands:

19

20

```python

21

from sh import ls, git, docker # Any system command

22

```

23

24

For classes and utilities:

25

26

```python

27

from sh import Command, pushd, glob, ErrorReturnCode

28

```

29

30

For contrib commands:

31

32

```python

33

from sh.contrib import git, sudo, bash # Enhanced command versions

34

```

35

36

## Basic Usage

37

38

```python

39

import sh

40

41

# Call any system command as a Python function

42

output = sh.ls("-la", "/tmp")

43

print(output)

44

45

# Chain commands with pipes

46

result = sh.grep(sh.ps("aux"), "python")

47

48

# Run commands in the background

49

proc = sh.sleep(10, _bg=True)

50

print("Command running in background...")

51

proc.wait()

52

53

# Handle command output in real-time

54

def process_line(line):

55

print(f"Output: {line.strip()}")

56

57

sh.tail("-f", "/var/log/system.log", _out=process_line)

58

59

# Change directory temporarily

60

with sh.pushd("/tmp"):

61

files = sh.ls() # lists files in /tmp

62

print(files)

63

# Back to original directory

64

65

# Handle errors

66

try:

67

sh.ls("/nonexistent")

68

except sh.ErrorReturnCode_2 as e:

69

print(f"Command failed: {e}")

70

```

71

72

## Architecture

73

74

The sh library uses a dynamic command resolution system built around these core components:

75

76

- **Command**: Represents an un-run system program that can be configured and executed

77

- **RunningCommand**: Manages executing processes with advanced I/O handling and control

78

- **Dynamic Resolution**: Any attribute access (like `sh.ls`) creates Command objects for system programs

79

- **Exception Hierarchy**: Specific exception classes for different exit codes and signals

80

- **Process Management**: Background execution, real-time streaming, piping, and signal handling

81

82

This design enables treating shell commands as first-class Python objects while maintaining full control over process execution, I/O redirection, and error handling.

83

84

## Capabilities

85

86

### Command Execution

87

88

Core functionality for executing system commands with comprehensive process control, argument handling, and execution modes including foreground, background, and interactive execution.

89

90

```python { .api }

91

def __call__(*args, **kwargs): ... # Command execution

92

def bake(*args, **kwargs): ... # Pre-configure command arguments

93

```

94

95

[Command Execution](./command-execution.md)

96

97

### Process Management

98

99

Advanced process control including background execution, process monitoring, signal handling, and process lifecycle management with support for long-running commands.

100

101

```python { .api }

102

def wait(): ... # Wait for background process completion

103

def kill(): ... # Terminate running process

104

def terminate(): ... # Gracefully terminate process

105

def is_alive(): ... # Check if process is running

106

```

107

108

[Process Management](./process-management.md)

109

110

### Input/Output Handling

111

112

Comprehensive I/O redirection and streaming capabilities including real-time output processing, piping between commands, input feeding, and output capturing with multiple formats.

113

114

```python { .api }

115

def _out(callback): ... # Real-time output processing

116

def _err(callback): ... # Real-time error processing

117

def _in(data): ... # Feed input to command

118

def _piped: ... # Enable piping to other commands

119

```

120

121

[Input/Output Handling](./io-handling.md)

122

123

### Error Handling

124

125

Robust error handling system with specific exception classes for different failure modes, exit code management, and comprehensive error information capture.

126

127

```python { .api }

128

class ErrorReturnCode(Exception): ...

129

class ErrorReturnCode_1(ErrorReturnCode): ... # Exit code 1

130

class SignalException(Exception): ...

131

class TimeoutException(Exception): ...

132

class CommandNotFound(Exception): ...

133

```

134

135

[Error Handling](./error-handling.md)

136

137

### Contrib Commands

138

139

Enhanced command wrappers that provide optimized defaults and specialized functionality for common tools like git, sudo, bash, and ssh.

140

141

```python { .api }

142

@contrib("git")

143

def git(orig): ... # Git with optimized defaults

144

@contrib("sudo")

145

def sudo(orig): ... # Sudo with password handling

146

@contrib("bash")

147

def bash(orig): ... # Bash with -c flag pre-configured

148

```

149

150

[Contrib Commands](./contrib.md)

151

152

### Utilities and Helpers

153

154

Additional utilities including directory manipulation, enhanced globbing, logging, and command introspection tools for advanced shell integration scenarios.

155

156

```python { .api }

157

def pushd(path): ... # Directory context manager

158

def glob(pattern): ... # Enhanced glob with sh integration

159

class Logger: ... # Command execution logger

160

```

161

162

[Utilities](./utilities.md)

163

164

## Types

165

166

```python { .api }

167

class Command:

168

"""Represents an un-run system program."""

169

def __init__(self, path: str, search_paths=None): ...

170

def __call__(self, *args, **kwargs): ... # Returns str or RunningCommand

171

def bake(self, *args, **kwargs): ... # Returns new Command

172

def __str__(self) -> str: ... # String representation with path

173

def __repr__(self) -> str: ... # Formal string representation

174

def __eq__(self, other) -> bool: ... # Equality comparison

175

176

class RunningCommand:

177

"""Represents an executing command process."""

178

def wait(self): ...

179

def kill(self): ...

180

def terminate(self): ...

181

def signal(self, sig): ... # Send signal to process

182

def is_alive(self) -> bool: ...

183

@property

184

def pid(self) -> int: ... # Process ID

185

@property

186

def stdout(self) -> str: ...

187

@property

188

def stderr(self) -> str: ...

189

@property

190

def exit_code(self) -> int: ...

191

@property

192

def process(self): ... # Access to subprocess.Popen object

193

194

class ErrorReturnCode(Exception):

195

"""Base exception for command execution errors."""

196

def __init__(self, full_cmd: str, stdout: bytes, stderr: bytes): ...

197

@property

198

def exit_code(self) -> int: ...

199

@property

200

def full_cmd(self) -> str: ... # Complete command executed

201

@property

202

def stdout(self) -> bytes: ... # Command stdout output

203

@property

204

def stderr(self) -> bytes: ... # Command stderr output

205

206

class SignalException(Exception):

207

"""Exception raised when process is terminated by a signal."""

208

def __init__(self, full_cmd: str, signal_code: int): ...

209

210

class TimeoutException(Exception):

211

"""Exception raised when command times out."""

212

def __init__(self, full_cmd: str, timeout: float): ...

213

214

class CommandNotFound(Exception):

215

"""Exception raised when command cannot be found in PATH."""

216

def __init__(self, command: str): ...

217

218

class ForkException(Exception):

219

"""Exception raised when there's an error in the fork process."""

220

def __init__(self, command: str, error: str): ...

221

222

class Logger:

223

"""Memory-efficient command execution logger."""

224

def __init__(self, name: str, context: dict = None): ...

225

def log(self, level: str, message: str): ...

226

def info(self, message: str): ...

227

def debug(self, message: str): ...

228

def warning(self, message: str): ...

229

def error(self, message: str): ...

230

231

class GlobResults(list):

232

"""Enhanced list of glob results with additional methods."""

233

def __init__(self, results): ...

234

235

class StreamBufferer:

236

"""Advanced: Internal buffering implementation for I/O streams."""

237

def __init__(self, buffer_size: int = 0, encoding: str = 'utf-8'): ...

238

```