Build a Recipe Runner Mock in Python
A Python script that mocks a command runner recipe system: maps recipe names to shell commands, executes them with subprocess, and prints the output and exit code.
Python code
27 linesimport subprocess
import sys
def run_recipe(recipe: str) -> None:
"""Simulate a command runner recipe by printing the command and exit code."""
print(f"Running recipe: {recipe}")
result = subprocess.run(recipe, shell=True, capture_output=True, text=True)
print(f"Exit code: {result.returncode}")
if result.stdout:
print("stdout:", result.stdout.strip())
if result.stderr:
print("stderr:", result.stderr.strip())
if __name__ == "__main__":
recipes = {
"greet": "echo 'Hello from recipe runner!'",
"list-files": "ls -la",
"python-version": "python3 --version",
}
recipe_key = sys.argv[1] if len(sys.argv) > 1 else "greet"
if recipe_key in recipes:
run_recipe(recipes[recipe_key])
else:
print(f"Unknown recipe '{recipe_key}'. Available: {', '.join(recipes)}")
Output
Running recipe: greet
Exit code: 0
stdout: Hello from recipe runner!
How it works
This script uses subprocess.run() to execute shell commands safely with capture. It maps recipe keys to command strings in a dictionary, then calls a helper function that prints the command and its result. The shell=True flag allows the command to be interpreted by the shell, while capture_output=True and text=True capture stdout/stderr as strings. The main guard reads the recipe from sys.argv, falling back to 'greet'. This structure models how real command runners, like task runners or Makefiles, dispatch actions.
Common mistakes
- Using `shell=True` with untrusted input can lead to command injection.
- Not setting `capture_output=True` results in output being printed directly to the console.
- Forgetting to handle unknown recipe keys gracefully.
Variations
- Use `shlex.split()` to avoid `shell=True` and pass a list of arguments.
- Add a `--list` flag to display all available recipes without executing them.
Real-world use cases
- Creating a lightweight task runner for development workflows, similar to `invoke` or `just`.
- Prototyping a CI pipeline step that executes different commands based on a parameter.
- Building a mock service for testing CLIs that interact with a command execution layer.
Sponsored
More from Modern tooling
- Build a Textual TUI App Skeleton in Python easy
- Configure ruff linter rules in pyproject.toml with Python easy
- Data Conversion Helper Functions in Python easy
- How to Bind and Mock structlog Context in Python medium
- How to Build a Chainable Filter Helper in Python easy
- How to Build a Wheel with Hatchling in Python easy
Keep learning
Related tutorials and quizzes for this topic.