Created
March 10, 2016 18:19
-
-
Save diefans/b8bc601ca34ed8571771 to your computer and use it in GitHub Desktop.
Popen stdout/stderr generator by means of select.select
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import shlex | |
| import subprocess | |
| import select | |
| class stdout(str): | |
| """A string representation from stdout.""" | |
| class stderr(str): | |
| """A string representation from stderr.""" | |
| class Execution(object): | |
| """Provides an iterator over stdout and stderr lines from Popen process.""" | |
| def __init__(self, command): | |
| if isinstance(command, subprocess.Popen): | |
| self.proc = command | |
| else: | |
| self.proc = subprocess.Popen( | |
| isinstance(command, basestring) and shlex.split(command) or command, | |
| shell=False, | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.PIPE, | |
| # stdin=subprocess.PIPE, | |
| ) | |
| def __enter__(self): | |
| return self | |
| def __exit__(self, exc_type, exc_value, traceback): | |
| pass | |
| def __iter__(self): | |
| proc = self.proc | |
| stdout_fd = proc.stdout.fileno() | |
| stderr_fd = proc.stderr.fileno() | |
| line_factory = { | |
| stdout_fd: lambda: stdout(proc.stdout.readline()), | |
| stderr_fd: lambda: stderr(proc.stderr.readline()) | |
| } | |
| reads = [stdout_fd, stderr_fd] | |
| while True: | |
| rx, _, _ = select.select(reads, [], []) | |
| for fd in rx: | |
| factory = line_factory[fd] | |
| while True: | |
| line = factory() | |
| if line == '': | |
| break | |
| yield line | |
| if proc.poll() is not None: | |
| break | |
| @property | |
| def exitcode(self): | |
| return self.proc.returncode | |
| @property | |
| def pid(self): | |
| return self.proc.pid | |
| def test_execution(): | |
| with Execution('ls -la') as exe: | |
| for line in exe: | |
| print line.__class__.__name__, line, | |
| print "Exited with:", exe.exitcode |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment