def __init__(self, process, p_out=True, p_err=True):
        """

        :param subprocess.Popen process:
        :param p_out:
        :param p_err:
        :return:
        """
        self._p = process
        self._o = []
        self._e = []
        self._c = 255
        self._p_out = p_out
        self._p_err = p_err
        self._ostream = NonBlockingStreamReader(self._p.stdout)
        self._estream = NonBlockingStreamReader(self._p.stderr)

        # loop until the process ends
        while self._p.poll() is None:
            if not self._try_read():
                # minor delay to prevent cpu-cycling, but only if we were
                # unable to read anything.
                #
                # note: this actually makes the process block, removing
                # asynchronous-ness
                time.sleep(.01)

        # now that the subprocess has ended, flush out any remaining output
        self._try_flush(self._p.stdout)
        self._try_flush(self._p.stderr)

        # read whatever may have been flushed
        while self._try_read():
            pass

        # make sure to close out any open streams
        self._try_close(self._p.stdout)
        self._try_close(self._p.stderr)

        # snag the return code
        self._c = self._p.returncode
class ProcessReader(object):
    """
    Asynchronously reads info from a subprocess' error and output streams.
    """

    def __init__(self, process, p_out=True, p_err=True):
        """

        :param subprocess.Popen process:
        :param p_out:
        :param p_err:
        :return:
        """
        self._p = process
        self._o = []
        self._e = []
        self._c = 255
        self._p_out = p_out
        self._p_err = p_err
        self._ostream = NonBlockingStreamReader(self._p.stdout)
        self._estream = NonBlockingStreamReader(self._p.stderr)

        # loop until the process ends
        while self._p.poll() is None:
            if not self._try_read():
                # minor delay to prevent cpu-cycling, but only if we were
                # unable to read anything.
                #
                # note: this actually makes the process block, removing
                # asynchronous-ness
                time.sleep(.01)

        # now that the subprocess has ended, flush out any remaining output
        self._try_flush(self._p.stdout)
        self._try_flush(self._p.stderr)

        # read whatever may have been flushed
        while self._try_read():
            pass

        # make sure to close out any open streams
        self._try_close(self._p.stdout)
        self._try_close(self._p.stderr)

        # snag the return code
        self._c = self._p.returncode

    def _try_flush(self, stream):
        if not stream.closed:
            stream.flush()

    def _try_read(self):
        out = self._ostream.readline()
        if out is not None:
            if self._p_out:
                print(out)
            self._o.append(out)

        err = self._estream.readline()
        if err is not None:
            if self._p_err:
                print(err)
            self._e.append(err)

        # true if something was read
        return out is not None or err is not None

    def _try_close(self, stream):
        while not stream.closed:
            try:
                stream.close()
                break
            except IOError, e:
                if 'concurrent operation on the same file object' in str(e):
                    # more to read?
                    while self._try_read():
                        pass
                    continue
                raise