Skip to content

Instantly share code, notes, and snippets.

@W4RH4WK
Last active October 22, 2022 15:40
Show Gist options
  • Save W4RH4WK/09331030e1d903283787b289e0356522 to your computer and use it in GitHub Desktop.
Save W4RH4WK/09331030e1d903283787b289e0356522 to your computer and use it in GitHub Desktop.
Python run shell command shorthand
import subprocess
import sys
from asyncio import Future
from contextlib import contextmanager
@contextmanager
def ParallelSh():
"""
Context manager that provides a function to run processes in parallel. All
processes have terminated when the context manager exists. An exception is
raised if one (or more) processes failed. Resulting stdout is provided via
a Future.
"""
procs = []
def run(cmd, input=None, **kwargs):
if input is not None:
kwargs['stdin'] = subprocess.PIPE
proc = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE, stderr=sys.stderr,
encoding='UTF-8', **kwargs)
if input is not None:
proc.stdin.write(input)
proc.stdin.close()
proc.stdin = None
proc.stdout_future = Future()
procs.append(proc)
return proc.stdout_future
yield run
for proc in procs:
proc.wait()
proc.stdout_future.set_result(proc.communicate()[0])
for proc in procs:
if proc.returncode:
raise subprocess.CalledProcessError(proc.returncode, proc.args,
output=proc.stdout_future.result())
# Basic usage:
with ParallelSh() as sh:
date1 = sh('date') # sh returns a Future containing stdout
sh('sleep 1')
date2 = sh('date')
print(date1.result())
print(date2.result())
# Provide some input:
with ParallelSh() as sh:
wc = sh('wc -l', input='foo\nbar\n')
print(wc.result())
# stderr is forwarded:
with ParallelSh() as sh:
sh('echo some error 1 >&2')
sh('echo some error 2 >&2')
# Exception on error, after all processes have terminated
try:
with ParallelSh() as sh:
date = sh('date')
sh('false')
except Exception as e:
print(f'date still valid: {date.result()}')
print(f'Exception caught: {e}')
import sys
import subprocess
def sh(cmd, **kwargs):
return subprocess.run(cmd, shell=True, check=True,
stdout=subprocess.PIPE, stderr=sys.stderr,
encoding='UTF-8', **kwargs).stdout
# Basic usage:
print(sh('date'))
# Provide some input:
print(sh('wc -l', input='foo\nbar\n'))
# stderr is forwarded:
sh('echo some error >&2')
# Exception on error
try:
sh('false')
except Exception as e:
print(f'Exception caught: {e}')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment