#!/usr/bin/env python3 import os import select DEFAULT_BUFFER_SIZE_BYTES = 8196 DEFAULT_READ_TIMEOUT_SECONDS = 1.0 def rselect(fd, timeout_seconds=None): """ Wait until file descriptor is ready for reading. Return True if ready. Return False if timeout was reached. select.select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist) """ rlist, wlist, xlist = select.select([fd], [], [], timeout_seconds) return fd in rlist def non_blocking_os_read(fd, buffer_size_bytes=DEFAULT_BUFFER_SIZE_BYTES, timeout_seconds=DEFAULT_READ_TIMEOUT_SECONDS): if rselect(fd, timeout_seconds=timeout_seconds): return os.read(fd, buffer_size_bytes) else: return None # usage / example import logging import subprocess import sys logging.basicConfig(level=logging.INFO) read_fd, write_fd = os.pipe() p = subprocess.Popen(['ping', '1.1.1.1'], stdout=write_fd) while p.poll() is None: logging.debug('waiting...') stdout_data = non_blocking_os_read(read_fd) if stdout_data: logging.info('read {} bytes'.format(len(stdout_data))) sys.stdout.buffer.write(stdout_data) sys.stdout.flush() else: logging.info('timeout')