non_blocking_os_read.py 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. #!/usr/bin/env python3
  2. import os
  3. import select
  4. DEFAULT_BUFFER_SIZE_BYTES = 8196
  5. DEFAULT_READ_TIMEOUT_SECONDS = 1.0
  6. def rselect(fd, timeout_seconds=None):
  7. """ Wait until file descriptor is ready for reading.
  8. Return True if ready. Return False if timeout was reached.
  9. select.select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)
  10. """
  11. rlist, wlist, xlist = select.select([fd], [], [], timeout_seconds)
  12. return fd in rlist
  13. def non_blocking_os_read(fd, buffer_size_bytes=DEFAULT_BUFFER_SIZE_BYTES, timeout_seconds=DEFAULT_READ_TIMEOUT_SECONDS):
  14. if rselect(fd, timeout_seconds=timeout_seconds):
  15. return os.read(fd, buffer_size_bytes)
  16. else:
  17. return None
  18. # usage / example
  19. import logging
  20. import subprocess
  21. import sys
  22. logging.basicConfig(level=logging.INFO)
  23. read_fd, write_fd = os.pipe()
  24. p = subprocess.Popen(['ping', '1.1.1.1'], stdout=write_fd)
  25. while p.poll() is None:
  26. logging.debug('waiting...')
  27. stdout_data = non_blocking_os_read(read_fd)
  28. if stdout_data:
  29. logging.info('read {} bytes'.format(len(stdout_data)))
  30. sys.stdout.buffer.write(stdout_data)
  31. sys.stdout.flush()
  32. else:
  33. logging.info('timeout')