Since the event loop can see and notify the end of the process before reading the rest of the data for stdout / stderr, we need to check the PIPE close events in addition to the process exit event.
This is the correction of aknuds1 answer:
class SubprocessProtocol(asyncio.SubprocessProtocol): def __init__(self): self._exited = False self._closed_stdout = False self._closed_stderr = False @property def finished(self): return self._exited and self._closed_stdout and self._closed_stderr def signal_exit(self): if not self.finished: return loop.stop() def pipe_data_received(self, fd, data): if fd == 1: name = 'stdout' elif fd == 2: name = 'stderr' text = data.decode(locale.getpreferredencoding(False)) print('Received from {}: {}'.format(name, text.strip())) def pipe_connection_lost(self, fd, exc): if fd == 1: self._closed_stdout = True elif fd == 2: self._closed_stderr = True self.signal_exit() def process_exited(self): self._exited = True self.signal_exit()
source share