Skip to content

Instantly share code, notes, and snippets.

@algal
Last active October 23, 2018 06:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save algal/7ecf357d7ff2545dc67e6f8d70f62d7c to your computer and use it in GitHub Desktop.
Save algal/7ecf357d7ff2545dc67e6f8d70f62d7c to your computer and use it in GitHub Desktop.
# known-good: python 3.7.0
class RunOutput(object):
def __init__(self, return_code, stdout, stderr):
self.return_code = return_code
self.stdout = stdout
self.stderr = stderr
def run_tee(s):
"""Runs shell command s, returning a RunOutput with (return_code, stdout, stderr).
Returns stdout and stderr as unicode strings trimmed of whitespace at ends.
Also, transparently passes through stdout and stderr unaltered, like tee."""
import subprocess, select
print("\nrun_tee:\n about to call command: {}\n".format(s))
process = subprocess.Popen(s, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
sout_fd = process.stdout.fileno()
serr_fd = process.stderr.fileno()
so = b''
se = b''
while process.poll() is None:
fds, _, _ = select.select([sout_fd, serr_fd], [], [], .1)
if sout_fd in fds:
new_so = process.stdout.readline()
sys.stdout.buffer.write(new_so)
sys.stdout.buffer.flush()
so += new_so
if serr_fd in fds:
new_se = process.stderr.readline()
sys.stderr.buffer.write(new_se)
sys.stderr.buffer.flush()
se += new_se
new_so = process.stdout.read()
sys.stdout.buffer.write(new_so)
sys.stdout.buffer.flush()
so += new_so
new_se = process.stderr.read()
sys.stderr.buffer.write(new_se)
sys.stderr.buffer.flush()
se += new_se
rc = process.returncode
r = RunOutput(rc, so.decode().strip(), se.decode().strip())
print("\nrun_tee:\n finished calling command: {}\n return_code: {}\n".format(s,r.return_code))
return r
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment