Pysh/Pype
Python source file preprocessor/interpreter and subprocess pipe manager to enable running in-line bash/shell code during python runtime.
#!/usr/bin/env python from pysh import pysh pysh() #$@ echo "Pysh activated" stdout = ""#$ echo "This is standard out" print(stdout) ##@!python print("Python through a pysh pype")
Use #$ flagged directives to signify shell code to be piped through a subprocess.
When you run pysh() execution stops, and the source file will be processed with regex to extract and replace the code blocks with a subprocess wrapper, and then the source file itself is run through it.
Real usage
# Script your system in parallel with your python code execution # Do anything you can in bash e.g. build_service() #$ cd ~/hosted/myservice && docker compose up aggregate_assets() crf = "23" in_file = "/path/in.mp4" out_file = "/path/out.mp4" fmpg_result = ""#$ ffmpeg -i {$in_file$} \ #$ -crf {$crf$} -o {$out_file$} \ #$ && rm {$in_file$} process_assets(process_fmpg_stdout(fmpg_result)) print("Process complete")
Installation
From PyPI:
pip3 install pyshpype
Git to local folder:
pip3 install -e "git+https://github.com/blipk/pysh.git#egg=pysh"
General syntax
#!/usr/bin/python from pysh import pysh pysh() #$ echo "pysh activated" >> .pysh # Use the @ flag to always print(stdout) to main sys.stdout #$@ echo "hello from bash" # This is a python comment #$@ ls . # shell eol comment ##$ sudo rm -rf / # disable pysh line with pysh comment # Capture stdout from the shell subprocess stout = ""#$ echo "I'm actually a bytes string" print(stdout.decode("UTF-8")) # Pass any python variable thats in scope to the pysh script my_var = "hello" stdout = ""#$ echo "{$myvar$}" # run external script with double $ #$$ my_script.sh # optionally pass arguments to it #$$ argumentative_script.sh arg1 arg2 # Use the ! flag to change the shell that interprets the script # must support -c command_strings or filepath if external $$ #$!sh echo "simple" #$!perl oysters.pl #$$@!bash printscript.sh # Multiple flags/features stdout = ""#$@!python import time #$ print("The time and date", time.asctime()) # Use the % flag to catch errors, # otherwise they will be printed but not raised try: result = ""#$$% tests/dinger/notfoundscript.sh "argone" except SystemExit as e: print("Error", e) if __name__ == "main": print("Before the above script blocks are run")
Multiple inline pysh
# Pysh runs code in blocks that are executed in-place # Block 0 #$ cd $HOME stdout_block1 = ""#$ echo "first block is multiline" #$ echo "line1" #$ echo "line2" # The last script block won't be run sys.exit(1) stdout_block2 == ""#$ echo "Second" #$ echo "Block"
Advanced usage
# run pysh manually from pysh import Pysh source_file = __file__ pysher = Pysh(source_file) blocks = pysher.findblocks() # Run a a single block blocks[0].run() # Not run in-place, no stdout. Silent. # Run script block again, and print stdout with label for block blocks[0].runp() # Run all wanted blocks sequentially at this point, # and print their stdout with labels run_blocks = [block.runp() for block in blocks if "/root" in block.srcs] # Start the python interpreter with pysh on source_file # This is the same as running pysh(__file__) pysher.shyp() #$ echo "pysh enabled" # Switch to another source file and run it through pysh pysher.pysh(__file__) # Equivalent to above pysher.updatesrc(__file__) pysher.pysh() # Get information about the script blocks at runtime t_block = pysher.blocks[0] print(t_block.hasrun, t_block.returncode) print(t_block.srcs, "\n--\n", t_block.stdout)