How to stream stdout/stderr from a child process using asyncio, and obtain its exit code after?

前端 未结 3 1474
一向
一向 2020-12-19 15:51

Under Python 3.4 on Windows, I need to stream data written to stdout/stderr by a child process, i.e. receive its output as it occurs, using the asyncio framework introduced

3条回答
  •  情书的邮戳
    2020-12-19 16:26

    Since the event loop may see and notify the process exit before reading the remaining data for stdout/stderr, we need to check PIPE close events in addition to the process exit event.

    This is a correction for 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()
    

提交回复
热议问题