Intuitive API to safely start and communicate with processes in Python
Project description
Subrun
Intuitive API to safely start and communicate with processes in Python.
This project is part of the Pyrustic Open Ecosystem.
Installation . Demo . Latest . Documentation
Table of contents
Overview
Python comes with the subprocess module that allows to spawn new processes. In a unified module, subprocess provides enhancements over previous functions for the same task.
Based on the subprocess module, Subrun is a library that makes convenience and security a priority for spawning new processes. With Subrun, commands are provided as strings (or as a sequence of strings) that are safely executed without involving the system shell and a consistent NamedTuple is returned to give you useful information about what just happened (success boolean, return codes from each process of a pipeline, boolean timeout_expired, et cetera).
The library is made up of two categories of functions:
- Three functions that synthesize the operations you will need to perform: run, ghostrun, and capture.
- Three base functions that helped build the previous functions: create, wait, and communicate.
These functions, originally designed to spawn one process at a time, are mirrored in subrun.pipeline
, a module dedicated to the pipeline mechanism.
Operations
Let's take a look at run, ghostrun, and capture, three convenience functions that attempt to synthesize use cases into three eponymous operations.
Run
Use the run function to spawn a new process that a user can interact with from the command line. This function returns a NamedTuple with useful information (e.g., the return code, et cetera).
import subrun
command = "python -m this"
subrun.run(command) # returns a NamedTuple
Note: Subrun recognizes the
python
command and replaces it with the fully-qualified path of the executable binary for the current Python interpreter.
The run function also accepts these keywords-arguments: input
, cwd
, stdin
, stdout
, stderr
, and timeout
.
Example
hello.py: Simple program that asks for your name and gender, then greets you.
# hello.py
name = input()
gender = input()
msg = "Hello {} ! You are a {} !".format(name, gender)
print(msg)
script.py: Simple script that uses subrun to run hello.py and programmatically send it an arbitrary name and gender.
# script.py
import subrun
command = "python -m hello"
subrun.run(command, input="Alex\nMale")
# note that you can also set the 'cwd' parameter
# (current working directory)
# also, in this specific example,
# if you don't set the 'input' programmatically,
# it will be prompted to the user
command line: Let's run script.py !
$ python -m script
Hello Alex ! You are a Male !
Ghostrun
Use the ghostrun function to run a command without any feedback. Ghostrun is like the run function with one twist: stderr
and stdout
are redirected to devnull. This function returns a NamedTuple with useful information (e.g., the return code of the process, the success
boolean, et cetera).
script.py: This script uses subrun to ghostrun the command "python -m this".
# script.py
import subrun
command = "python -m this"
subrun.ghostrun(command) # returns a NamedTuple instance
command line: Let's run script.py !
$ python -m script
$
Capture
Use the capture function to run and capture the output of a command. This function returns a NamedTuple instance with useful information (e.g., the return code of the process, the stdout
data, the stderr
data, et cetera).
# script.py
import subrun
command = "python -m this"
info = subrun.capture(command) # returns a NamedTuple instance
# info.output contains the Zen Of Python as encoded bytes
Base functions
The run, ghostrun, and capture functions use three base functions:
- create: Run a command and return a process object.
- wait: Wait for a process to terminate.
- communicate: Interact with a process.
The run and ghostrun functions use create and wait base functions. The capture function use create and communicate base functions.
Example
import subrun
# === Create and Wait ===
# Command
command = "python -m this"
# Create the process with the command
process = subrun.create(command)
# Wait the process to end
info = subrun.wait(process)
# === Create and Communicate ===
# Command
command = "python -m hello"
# Create the process with the command
process = subrun.create(command)
# Capture the output of the process
info = subrun.communicate(process, input="Alex\nMale")
Pipeline
The subrun.pipeline
module reproduces the same API as in subrun
with a twist: you must provide more than one command which will be chained and executed.
Example
The run, ghostrun, and capture functions are defined in the subrun.pipeline
module to process a pipeline of commands:
from subrun import pipeline
command1 = "python -m hello"
command2 = "program arg1 arg2"
command3 = "/path/to/program --arg data"
# === Run ===
# Run three commands pipeline. A NamedTuple instance is returned
pipeline.run(command1, command2, command3, input="Alex\nMale")
# === Ghostrun ===
# Ghostrun three commands pipeline. A NamedTuple instance is returned
pipeline.ghostrun(command1, command2, command3)
# === Capture ===
# Capture three commands pipeline. A NamedTuple instance is returned
info = pipeline.capture(command1, command2, command3)
The create, wait, and communicate base functions are also defined in the subrun.pipeline
module to process a pipeline of commands:
from subrun import pipeline
command1 = "python -m hello"
command2 = "program arg1 arg2"
command3 = "/path/to/program --arg data"
# === Create and Wait ===
# Create a generator so that you can iterate over created processes
generator = pipeline.create(command1, command2, command3)
# Wait the process to end
pipeline.wait(generator)
# === Create and Communicate ===
# Create a generator so that you can iterate over created processes
generator = pipeline.create(command1, command2, command3)
# Capture the output of the process
pipeline.communicate(generator)
Related project
Backstage is a language-agnostic command-line tool that allows the developer to define, coordinate and use the various resources at his disposal to create and manage a software project.
Backstage uses Subrun extensively.
Discover Backstage !
Installation
Subrun is cross platform and versions under 1.0.0 will be considered Beta at best. It is built on Ubuntu with Python 3.8 and should work on Python 3.5 or newer.
For the first time
$ pip install subrun
Upgrade
$ pip install subrun --upgrade --upgrade-strategy eager
Demo
A demo is available to play with as a Github Gist. Feel free to give a feedback in the comments section.
Play with the Demo.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.