#!/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')