Skip to main content

A more ergonomic subprocess alternative with bash-like pipe syntax

Project description

shell-pilot

A more ergonomic subprocess alternative for Python with bash-like pipe syntax.

Why?

Python's subprocess module is powerful but verbose. Compare:

# subprocess (the pain)
import subprocess
p1 = subprocess.Popen(['ls', '-la'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['grep', 'foo'], stdin=p1.stdout, stdout=subprocess.PIPE)
p3 = subprocess.Popen(['wc', '-l'], stdin=p2.stdout, stdout=subprocess.PIPE)
p1.stdout.close()
p2.stdout.close()
output = p3.communicate()[0]

# shell-pilot (the joy)
from shell_pilot import cmd
result = (cmd("ls -la") | cmd("grep foo") | cmd("wc -l")).run()

Installation

pip install shell-pilot

Usage

Basic Commands

from shell_pilot import cmd

# Simple command
result = cmd("echo hello world").run()
print(result.stdout)  # "hello world\n"

# Check success
if result.ok:
    print("Command succeeded")

Piping with |

Chain commands together just like in bash:

# Two-stage pipe
result = (cmd("cat /etc/hosts") | cmd("grep localhost")).run()

# Multi-stage pipe
result = (
    cmd("ps aux")
    | cmd("grep python")
    | cmd("grep -v grep")
    | cmd("wc -l")
).run()
print(f"Python processes: {result.stdout.strip()}")

Stdin, Environment & Working Directory

# Pass stdin
result = cmd("cat").with_stdin("hello from stdin").run()

# Set environment variables
result = cmd("echo $GREETING").with_env(GREETING="Hello").run()

# Change working directory
result = cmd("ls").with_cwd("/tmp").run()

Fluent API

All configuration methods return new instances, allowing fluent chaining:

result = (
    cmd("my-script")
    .with_stdin(input_data)
    .with_env(DEBUG="1", LOG_LEVEL="info")
    .with_cwd("/app")
    .run(check=True)
)

Error Handling

from shell_pilot import cmd, CommandError

# Option 1: Check the result
result = cmd("might-fail").run()
if not result.ok:
    print(f"Failed with code {result.returncode}: {result.stderr}")

# Option 2: Raise on failure
try:
    result = cmd("must-succeed").run(check=True)
except CommandError as e:
    print(f"Command failed: {e.result.stderr}")

# Option 3: Chain raise_on_error()
result = cmd("risky-command").run().raise_on_error()

Async Support

import asyncio
from shell_pilot import cmd

async def main():
    # Single async command
    result = await cmd("echo async").run_async()

    # Async pipeline
    result = await (
        cmd("cat largefile.txt")
        | cmd("grep pattern")
        | cmd("sort -u")
    ).run_async()

asyncio.run(main())

API Reference

cmd(command, stdin=None, env=None, cwd=None)

Create a command. Strings are automatically parsed (e.g., "ls -la" becomes ["ls", "-la"]).

Methods:

  • .run(check=False) - Execute synchronously
  • .run_async(check=False) - Execute asynchronously
  • .with_stdin(text) - Set stdin input
  • .with_env(**vars) - Add environment variables
  • .with_cwd(path) - Set working directory
  • .raise_on_error() - Raise CommandError if failed
  • | - Pipe to another command

Result

Attributes:

  • .stdout - Standard output as string
  • .stderr - Standard error as string
  • .returncode - Exit code
  • .ok - True if returncode is 0

Convenience Functions

from shell_pilot import run, run_async

result = run("ls -la")                # Quick sync execution
result = await run_async("ls -la")    # Quick async execution

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

shell_pilot-0.1.3.tar.gz (5.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

shell_pilot-0.1.3-py3-none-any.whl (5.9 kB view details)

Uploaded Python 3

File details

Details for the file shell_pilot-0.1.3.tar.gz.

File metadata

  • Download URL: shell_pilot-0.1.3.tar.gz
  • Upload date:
  • Size: 5.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.8

File hashes

Hashes for shell_pilot-0.1.3.tar.gz
Algorithm Hash digest
SHA256 36f65ee2b39fd1130c5a3f4a881e6cfa025ac376a7eaec7affe18883e9e5ecab
MD5 9cd0d42fbf35a6ea1ec016faccc21833
BLAKE2b-256 c366b3c051ed4ddf5a8663af232ae870e8ff446da2c6d355e4335949df6df0d9

See more details on using hashes here.

File details

Details for the file shell_pilot-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for shell_pilot-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 0b8d90ade58677cfb2bd5eaff2d53eac190611c316a43e0c277eff02f5eeac32
MD5 786b339653d3a4e61b250fd438a32a09
BLAKE2b-256 5aa53ebf1856d862449d4ab1ed82b97c74a294ccafd92c234041cfda5fe00f57

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page